티스토리 뷰
1) 파일업로드 컨셉설명
Multipart?
- Multipart는 보통 파일을 전송할 때 사용합니다.
- 웹 클라이언트가 요청을 보낼 때 HTTP프로토콜의 바디 부분에 데이터를 여러 부분으로 나눠서 보내며, 그림과 같이 Content-Type, 파일 이름, 파일 정보 등으로 나뉜 부분을 연결하여 전송합니다.
- 이렇게 여러 부분으로 나눠서 오는 것을 multipart 데이터라고 합니다.
HttpServletRequest는 파일 업로드를 지원 안 함
- HttpServletRequest는 웹 클라이언트가 전달하는 Multipart데이터를 쉽게 처리하는 메소드를 제공하지 않습니다.
- 서블릿에서 파일 업로드를 처리하려면 별도의 라이브러리를 사용해야 합니다. 대표적인 라이브러리가 아파치 재단의 commons-fileupload입니다.
- HttpServletRequest는 HTTP 프로토콜의 바디 부분을 읽어들이는 InputStream만을 지원하기에 사용자는 이런 InputStream을 이용해서 multipart 부분을 잘 나눠서 사용을 해야 됩니다.
Spring MVC에서의 파일 업로드
- Spring MVC에서 파일을 업로드 하려면 몇 가지 라이브러리와 설정을 추가해야 합니다.
- commons-fileupload, commons-io 라이브러리 추가
- MultipartResolver Bean 추가
파일 업로드를 위한 라이브러리 추가
- pom.xml에 아래의 dependency를 추가합니다.
<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> |
스프링 설정 추가
- DispathcerServlet은 준비 과정에서 "multipart/form-data"가 요청으로 올 경우 MultipartResolver를 사용합니다.
- 이를 위해서 MultipartResolver 객체를 생성하는 Bean을 설정해줘야 합니다.
@Bean public MultipartResolver multipartResolver() { org.springframework.web.multipart.commons.CommonsMultipartResolver multipartResolver = new org.springframework.web.multipart.commons.CommonsMultipartResolver(); multipartResolver.setMaxUploadSize(10485760); // 1024 * 1024 * 10 return multipartResolver; } |
파일 업로드 폼
- 파일 업로드 시에는 form태그에 enctype(multipart/ form-data)설정이 되어 있어야 합니다.
- post 방식으로 전송해야 합니다.
- input 태그의 type은 file로 지정해야 합니다.
- type이 file인 input 태그가 여러 개 있고 name 속성의 값이 같다면 file이 배열 형태로 컨트롤러에게 전달이 되게 됩니다.
<form method="post" action="/upload" enctype="multipart/form-data"> ...... <input type="file" name="file"> <input type="submit"> </form> |
Controller에서의 업로드 처리
- 폼으로부터 전달되는 파일 정보를 받아들이는 Controller를 추가를 해야합니다. 파일 정보는 파라미터로 전달되며 이 때 MultipartFile type으로 전달이 되게 됩니다.
- @PostMapping이 사용되어야 합니다.
- 업로드 파일이 하나일 경우 @RequestParam("file") MultipartFile file
- 업로드 파일이 여러 개일 경우 @RequestParam("file") MultipartFile[] files (배열로 사용)
- MultipartFile의 메소드를 이용해서 파일 이름, 파일 크기 등을 구하고 InputStream을 얻어 파일을 서버에 저장합니다.
- 파일은 서버의 파일 시스템에 저장하고 파일 정보는 DB에 저장합니다.
Controller에서의 다운로드 처리
- 서버의 특정 디렉토리는 외부에서 접근할 수가 없기에 파일을 외부에서 사용할 수 있도록 하려면 다운로드 기능을 제공해야 됩니다.
- 파일 다운로드와 관련된 헤더 정보를 출력합니다.
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;"); |
- 파일을 다운로드하는 Controller 메서드에서는 먼저 헤더 정보에 사용자가 다운 받으려는 파일 정보와 함께 캐시를 사용하지 않도록 설정을 해줘야 됩니다. 그리고 파일 정보를 HttpServlet Response의 OutputStream을 이용해서 출력해야 사용할 수 있습니다.
- 파일을 읽어 HttpServletResponse의 OutputStream으로 출력합니다.
생각해보기
- HTTP프로토콜의 바디 부분에 스트림(stream)방식으로 전달되는 Multipart를 읽어들이기 위해 아파치 재단의 commons-fileuplaod라이브러리를 이용한다고 했습니다. Multipart형식에 대해 좀 더 상세히 알아보고, 이를 직접 파싱하려면 어떻게 해야 할지 생각해보세요.
참고 자료
[참고링크] FileUpload – Home
https://commons.apache.org/proper/commons-fileupload/
[참고링크] Convenient way to parse incoming multipart/form-data parameters in a Servlet
'부스트코스 웹 프로그래밍 > 6. 웹 앱 개발: 예약서비스 4' 카테고리의 다른 글
3. 파일 업로드 & 다운로드 - BE (3) (0) | 2019.08.13 |
---|---|
3. 파일 업로드 & 다운로드 - BE (2) (0) | 2019.08.13 |
2. 로깅 - BE (3) (0) | 2019.08.13 |
2. 로깅 - BE (2) (0) | 2019.08.13 |
2. 로깅 - BE (1) (0) | 2019.08.13 |