요구사항에 엑셀다운로드 기능을 넣어달라는 의견이 있었다. 프로젝트 내부에 엑셀 생성 로직이 있어서 기존 소스를 활용하려고 하는데, 파일다운로드창(?) 계속 보이질 않았다. 에러도 안떠서 한참을 헤맸다.
결론은, 백엔드에서는 파일은 잘만 만들었고, 클라이언트에서 만든 파일을 받지 못하는 문제였다.
엑셀 다운로드 기본원리?
엑셀다운로드의 기본원리는 간단하다.
1. 클라이언트(브라우저)에서 jQuery ajax 요청을 보낸다.
2. 서버(Spring Controller)에서 해당 요청을 받아 데이터를 처리하고, 엑셀 파일을 생성한다.
3. 생성된 엑셀 파일을 클라이언트로 전송하여 다운로드한다.
이 세가지중에 내가 겪은 문제는 ajax응답을 어떻게 받을 것인지 헤더 설정하는 부분이 잘못됬기 때문이었다.
내가 파일다운로드를 요청했던 방식은 일반적인 ajax호출 방식이다.
$.ajax({
url: '/api/data',
type: 'GET',
success: function(response) {
// 응답 데이터 처리
console.log(response);
},
error: function(error) {
// 에러 처리
console.error(error);
}
});
파일 다운로드의 경우는 형태가 좀 다르다.
$.ajax({
url: '/api/download/excel',
type: 'GET',
xhrFields: {
responseType: 'blob' // 바이너리 데이터로 응답 받기
},
success: function(response) {
var blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'example.xlsx';
link.click();
},
error: function(error) {
// 에러 처리
console.error(error);
}
});
xhrFields 속성은 jQuery의 ajax 메서드를 사용하여 AJAX 요청을 보낼 때 추가적인 XMLHTTPRequest 설정을 지정하는 데 사용한다.
위 코드에서는 응답을 바이너리 데이터(blob)로 받기위해 xhrFields 속성을 추가로 사용한다. Blob 객체를 생성하고 이를 다운로드 링크로 만들고 클릭 이벤트를 트리거하여 파일을 다운로드시키는 형태다.
우리가 사용한 방법은 $.fileDownload이다.
$.fileDownload를 이용하기 위해서는, jQuery 라이브러리와 함께 추가로 fileDownload.js를 사용해야 한다.
$.fileDownload('/api/download/excel',{
httpMethod: "POST", // 요청 메서드
data: data, // 서버로 전송할 데이터
})
.done(function(){
// 다운로드 성공 시
})
.fail(function(){
var failMsg = "파일을 다운로드하지 못했습니다.";
alert(failMsg);
});
서버측에서는 Apache POI 라이브러리를 사용한다. Apache POI는 자바에서 MS 오피스 파일을 읽고 쓰는 기능을 제공하는 라이브러리이다.
클라이언트에서 파일을 받기위해 http 헤더를 추가해야한다.
res.setHeader("Set-Cookie", "fileDownload=true; path=/");
res.setHeader("Content-Disposition","attachment;filename=" + (URLEncoder.encode(("fileName.xlsx"),"UTF-8")));
res.setHeader("Content-Type", "application/vnd.ms-excel; charset=MS949");
res.setHeader("Content-Description", "JSP Generated Data");
res.setHeader("Content-Transfer-Encoding", "binary;");
res.setHeader("Pragma", "no-cache;");
res.setHeader("Expires", "-1;");
- Set-Cookie: 클라이언트에게 쿠키를 설정하도록 지시, 루트 경로(/)에 적용됨. 일반적으로 파일 다운로드가 성공적으로 시작되었음을 클라이언트에 알리는 데 사용됨.
- Content-Disposition: 클라이언트에게 파일을 다운로드(attachment)로 처리하도록 지시, 다운로드할 파일의 이름을 설정한다. 여기서 excelName 변수에 .xlsx 확장자를 붙여서 파일 이름을 지정한다. 파일이름은 UTF-8로 인코딩 시킴.
- Content-Type: 응답의 콘텐츠 타입을 설정, 엑셀 파일 형식을 나타내는 application/vnd.ms-excel로 설정. 문자 인코딩은 MS949
- Content-Description: 응답에 대한 설명을 제공 , "JSP Generated Data"로 설정되어 JSP로 생성된 데이터임을 나타냄.
- Content-Transfer-Encoding: 콘텐츠 전송 인코딩을 설정, 바이너리 데이터로 인코딩되어 전송됨
- Pragma: HTTP 1.0 호환 캐시 제어 헤더, 캐시를 사용하지 않도록 지시
- Expires: 캐시 만료 시간을 설정, -1 로 설정하여 캐시를 즉시 만료시키고, 항상 최신 데이터를 받아오도록함.
< 이어서 계속,, >
'로그' 카테고리의 다른 글
[JS] JSP에서 템플릿 리터럴, 백틱(`) 사용하기 (0) | 2024.07.16 |
---|---|
The package org.xml.sax is accessible from more than one module 에러 해결하기 (0) | 2024.06.30 |
[GCP] Google Source Repository에서 클론하기 (0) | 2024.03.21 |