본문 바로가기
개발/JavaScript

[Ajax] 파일 file 다운로드 받기

by zuzuu 2021. 11. 30.
반응형

 

결론부터 말하자면 xhr.responseType = "blob" 로 설정해야 한다!

기존에 사용하던 제이쿼리 버전이 1.11.1이였는데 이 버전은 blob이 적용안되더라..

버전 문제인줄 모르고 한참을 씨름 했는데 3.6.0으로 올리니까 해결됐다. (어떤 버전부터 되는 건지는 모르겠음)

 
 
아래 예시 참조!!
 
let options = { 
		url: "[[@{/}]]download" 
		, beforeSubmit  : loadingAjaxImage 
		, contentType: "application/x-www-form-urlencoded;charset=UTF-8" 
		, xhr: function () { 
				let xhr = new XMLHttpRequest(); 
				xhr.onreadystatechange = function () { 
                    //response 데이터를 바이너리로 처리한다. 세팅하지 않으면 default가 text 
					xhr.responseType = "blob"; 
				}; 
				return xhr; 
			} 
		, type: "post" 
		, success: function (data, message, xhr) { 
			hideAjaxImage(); 
			if (xhr.readyState == 4 && xhr.status == 200) {
				// 성공했을때만 파일 다운로드 처리하고
				let disposition = xhr.getResponseHeader('Content-Disposition'); 
				let filename; 
				if (disposition && disposition.indexOf('attachment') !== -1) { 
					let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; 
					let matches = filenameRegex.exec(disposition); 
					if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, ''); 
				} 
				let blob = new Blob([data]); 
				let link = document.createElement('a'); 
				link.href = window.URL.createObjectURL(blob); 
				link.download = filename; 
				link.click(); 
			}else{   
			    //실패했을때는 alert 메시지 출력
				alertPopup("다운로드에 실패하였습니다."); 
			} 
		} 
	}; 
	$("#testForm").ajaxSubmit( options ); 
}

 

ajax로 바꾼 이유

대량의 데이터라 생성하고 다운로드 처리하는 시간이 오래 걸리기 때문에 로딩이미지를 호출하기 위해서다

beforeSubmit : loadingAjaxImage -> 로딩 이미지 호출하는 부분

 

 Controller 예시

@RequestMapping("/download")
public ResponseEntity<?> download(@ModelAttribute TestVo testVo, HttpSession session){


	FileVo vo = this.testService.download(testVo);

	if(vo.getFileData() != null) {
		return ResponseEntity.ok()
				.contentType(MediaType.APPLICATION_OCTET_STREAM)
				.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + vo.getFileName() + "\"")
				.body(vo.getFileData());

	}else{
		return ResponseEntity.noContent().build();
	}
}

 

이렇게 파일이 다운로드 된다!

 

 

728x90
반응형

댓글