본문 바로가기

Programing/JVM(Java, Kotlin)

[HTTP & Spring MVC] 파일 다운로드 구현시 파일명 지정

HTML에서 a 엘리먼트로 하이퍼링크를 지정을 했을 경우 다운로드되는 파일의 이름은 URL 주소의 이름이 파일이다.

예를 들어 /download?filename=a.txt 라는 HTTP GET을 했을 경우 다운로드 받는 파일명은 a.txt인데 실제 받는 파일명은 download라는 이름이 된다.

이럴 경우 HTTP 응답 헤더중 Content-Disposition 를 지정해주면 된다.

바이너리일 경우를 위해 Content-Transfer-Encoding도 같이 지정한다.

 

HttpServletResponse response를 사용한다면,,,

response.setHeader("Content-Disposition", "attachment;filename=\""+filename+"\";");

response.setHeader("Content-Transfer-Encoding", "binary");

 

origin: http://gangzzang.tistory.com/126

 

혹은 ResponseEntity 반환 타입의 컨트롤러일 경우

@RequestMapping(method = RequestMethod.GET, value = "/download")

@ResponseBody

public ResponseEntity<InputStreamResource> download(@RequestParam("filename") String filename) throws IOException {

HttpHeaders responseHeaders = new HttpHeaders();

responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);

responseHeaders.set("Content-Disposition", "attachment;filename=\"" + filename + "\";");

responseHeaders.set("Content-Transfer-Encoding", "binary");

return new ResponseEntity<InputStreamResource>(getFileContent(filename), responseHeaders, HttpStatus.OK);

}

 

private InputStreamResource getFileContent(String filename) throws IOException

{

String path = String.format("%s%s", fsResource.getPath(), filename);

FileSystemResource resource = new FileSystemResource(path);

return new InputStreamResource(resource.getInputStream());

}

 

 

추가(2015-03-09)

Content-Disposition in HTTP를 학습(관련글 http://namocom.tistory.com/393)하고 나서 다국어를 처리하기 위해서는 팁이 필요했다. 어떤 사이트에 보니 브라우저 탐침을 통해 분기를 하게 되어 있는데 그렇게 할 필요는 없었다. (예1, 예2)

결국 아래와 같은 형태가 되었다. 아래 코드는 위에서 download 메서드의 일부이다.

String encordedFilename = URLEncoder.encode(filename,"UTF-8").replace("+", "%20");

responseHeaders.set("Content-Disposition",

  "attachment;filename=" + encordedFilename + ";filename*= UTF-8''" + encordedFilename);

tested Chrome 41.0.2272.76 m, Firefox 36.0.1, IE 6,7,8,10,11

 

업데이트 (2024-02-15)

다시 구현을 한다면 상수를 선언하고 스프링의 UriUtils을 사용해서 인코딩을 할 것이다.

왜냐하면 URLEncoder에서 공백을 %20으로 바꾸어주는 조작이 필요했는데 스프링의 퍼센트 인코딩은 그런 수고를 덜 수 있게 해준다.

import org.springframework.http.HttpHeaders
import org.springframework.web.util.UriUtils

String encordedFilename = UriUtils.encodeQuery(filename, StandardCharsets.UTF_8);
responseHeaders.set(HttpHeaders.CONTENT_DISPOSITION,
  "attachment;filename=" + encordedFilename + ";filename*= UTF-8''" + encordedFilename);