Spring 첨부파일 다운로드 구현하기
첨부파일이 이미지인 경우, 클릭했을 때 화면에 크게 원본 파일을 넘겨줘야 하고,
일반 첨부파일인 경우에는 다운로드를 기본으로 실행해야 한다.
MIME 타입이란?
https://developer.mozilla.org/ko/docs/Web/HTTP/Basics_of_HTTP/MIME_types
다운로드 시 MIME 타입은 고정되기 때문에 메서드는 아래와 같이 시작하게 된다.
@GetMapping(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public ResponseEntity<Resource> downloadFile(String fileName){
Resource resource = new FileSystemResource("C:\\upload\\" + fileName);
return null;
}
MIME 타입은 다운로드를 할 수 있는 application/octet- stream 으로 지정한다.
springframeword.core.io.Resource 인터페이스는 FileSystemResource, UriResource 등 다양한 리소스를 의미한다.
이제 HttpHeaders 객체를 이용해서 다운로드 시 파일 이름을 지정할 수 있다.
@GetMapping(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public ResponseEntity<Resource> downloadFile(String fileName){
Resource resource = new FileSystemResource("C:\\upload\\" + fileName);
String resourceName = resource.getFilename();
HttpHeaders headers = new HttpHeaders();
try {
headers.add("Content-Disposition", "attachment; filename="
+ new String(resourceName.getBytes(StandardCharsets.UTF_8), "ISO-8859-1"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new ResponseEntity<Resource> (resource, headers, HttpStatus.OK);
}
또한 Content-Disposition이라는 headerName을 사용해서, 다운로드 시 저장되는 이름을 지정한다.
https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Content-Disposition
Content-Disposition 응답 헤더는 콘텐츠가 첨부파일로 표시되는 지 여부를 나타내는 헤더이다.
다운로드 되어 로컬에 저장됨.
인코딩 처리도 해주어 한글 입력시 깨짐 현상을 방지한다.
추가적으로, Edge에서 다운로드 시 깨짐현상을 방지해야 한다.
HTTP 헤더 메세지 중 User-Agent 값을 이용해 브라우저의 프로그램이 종류를 구분할 수 있다.
@GetMapping(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public ResponseEntity<Resource> downloadFile(@RequestHeader("User-Agent")String userAgent, String fileName){
Resource resource = new FileSystemResource("C:\\upload\\" + fileName);
if (resource.exists() == false) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
String resourceName = resource.getFilename();
HttpHeaders headers = new HttpHeaders();
try {
String downloadName = null;
if(userAgent.contains("Trident")){
log.info("IE browser");
downloadName = URLEncoder.encode(resourceName, "UTF-8").replaceAll("\\+", " ");
} else if (userAgent.contains("Edge")) {
log.info("Edge browser");
downloadName = URLEncoder.encode(resourceName, "UTF-8");
} else{
log.info("Chrome browser");
downloadName = new String(resourceName.getBytes("UTF-8"), "ISO-8859-1");
}
headers.add("Content-Disposition", "attachment; filename=" + downloadName);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new ResponseEntity<Resource> (resource, headers, HttpStatus.OK);
}
서버에서 파일 이름에 UUID가 붙은 부분을 제거하고 순수하게 파일 이름으로 저장될 수 있도록 한다.