Multipart
- 웹 클라이언트가 요청을 보낼 때 HTTP프로토콜의 바디 부분에 데이터(파일 정보)를 여러 부분으로 나눠서 보내는 것으로, 보통 파일을 전송할 때 사용한다.
- HttpServletRequest는 웹 클라이언트가 전달하는 Multipart데이터를 쉽게 처리하는 메소드를 제공하지 않는다.
- 서블릿에서 파일 업로드를 처리하려면 별도의 라이브러리를 사용해야 하는데, 대표적인 라이브러리가 아파치 재단의 commons-fileupload 이다.
Spring MVC 설정
- Spring MVC에서 파일을 업로드 하려면 몇 가지 라이브러리와 설정을 추가해야 한다.
- commons-fileupload, commons-io 라이브러리 추가
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
- MultipartResolver Bean 추가
@Bean
public MultipartResolver multipartResolver() {
org.springframework.web.multipart.commons.CommonsMultipartResolver multipartResolver = new org.springframework.web.multipart.commons.CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(10485760);
return multipartResolver;
}
- DispathcerServlet은 준비 과정에서 "multipart/form-data"가 요청으로 올 경우 MultipartResolver를 사용한다.
- type=file인 input 태그가 여러 개 있고 name 속성의 값이 같다면 배열 형태로 컨트롤러에게 전달된다.
파일 업로드 폼
<form method="post" action="/upload" enctype="multipart/form-data">
...
<input type="file" name="file">
<input type="submit">
</form>
- 파일 업로드 시에는 form태그에 enctype설정이 되어 있어야 한다.
- 또한, post 방식으로 전송해야 한다.
Controller에서의 업로드 처리
- @PostMapping이 사용되어야 한다.
- 업로드 파일이 하나일 경우 @RequestParam("file") MultipartFile file
- 업로드 파일이 여러 개일 경우 @RequestParam("file") MultipartFile[] files
- MultipartFile의 메소드를 이용해서 파일 이름, 파일 크기 등을 구하고 InputStream을 얻어 파일을 서버에 저장한다.
Controller에서의 다운로드 처리
- 서버에 특정 디렉토리는 외부에서 접근할 수가 없는데, 이런 파일을 외부에서 사용할 수 있도록 하려면 다운로드 기능이 있어야 한다.
- 먼저, 헤더정보에 사용자가 다운받으려는 파일 정보와 함께, 캐시를 사용하지 않도록 설정해야 한다.
- 이후 파일 정보를 HttpServletResponse의 OutputStream으로 출력해야 사용할 수 있다.
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Type", contentType);
response.setHeader("Content-Length", fileLength;
response.setHeader("Pragma", "no-cache;");
response.setHeader("Expires", "-1;");