우선 스프링 프로젝트 내부에 파일 업로드 시 업로드한 파일이 저장되는 폴더인 upload 폴더가 있다고 가정해보자.
C:\sample-project\src\main\resources\static\upload
해당 upload 폴더에 저장되어 있는 star.jpg 파일을 다운로드 하는 로직은 다음과 같다.
public class FileVO {
/** 첨부파일 아이디 */
private Long fileId;
/** 게시글 아이디 */
private Long postId;
/** 파일 경로명 */
private String filePathNm;
/** 논리 파일명 */
private String logicFileNm;
/** 확장자 */
private String extension;
/** 등록일시 */
private String regDate;
/** 파일명 **/
private String fileNm;
...getter/setter
}
@Override
public void downloadFile(Long postId, HttpServletRequest request, HttpServletResponse response) throws Exception {
FileVO fileInfo = fileDAO.selectFileInfo(postId); // 게시글 id가 담긴
String systemPath = request.getSession().getServletContext().getRealPath("/") + ".."; // C:\sample-project\src\main\resources\static\upload
String filePath = systemPath + fileInfo.getFilePathNm(); // C:\sample-project\src\main\resources\static\upload/star.jpg
String fileNm = fileInfo.getFileNm(); // star.jpg
File file = new File(filePath); // 다운로드 될 파일 객체 생성
byte fileByte[] = FileUtils.readFileToByteArray(file); // 파일을 Byte 배열로 변환
response.setContentType("application/octet-stream"); // octet-stream: 데이터가 8비트 바이너리 배열임을 의미
response.setContentLength(fileByte.length);
// Content-Disposition에 attachment를 주는 경우, Body에 오는 값을 다운로드 받으라는 의미, fileName은 다운로드 될 파일명
response.setHeader("Content-Disposition", "attachment; fileName=\"" + URLEncoder.encode(fileNm,"UTF-8") +"\"");
// 전송 data의 인코딩 방식 설정
response.setHeader("Content-Transfer-Encoding", "binary");
// 데이터를 임시로 모아둔 버퍼의 출력 스트림을 출력
response.getOutputStream().write(fileByte);
response.getOutputStream().flush(); // 버퍼 비우기
response.getOutputStream().close(); // response 닫기
}
Axios로 요청하여 다운로드 받는 로직이다.
const download = async(post) => {
Axios.post('/api/sample/downloadFile',
{
postId: post.postId
},
{
responseType: 'blob', // 파일 다운로드를 위해 responseType을 'blob'으로 설정 -> response.data는 blob 객체가 된다.
}
).then((response) => {
// 응답 header에서 fileName 잘라내기
const name = response.headers["content-disposition"]
.split("fileName=")[1]
.replace(/"/g, "");
// 응답 데이터인 blob 객체 URL 생성
const url = window.URL.createObjectURL(response.data);
// 응답 데이터인 blob 객체 URL을 설정할 링크 생성
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", name);
link.style.cssText = "display: none";
// 링크를 body에 추가
document.body.appendChild(link);
// 강제로 click 이벤트 발생시키기
link.click();
link.remove();
})
}