티스토리 뷰

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 태그의 typefile로 지정해야 합니다.
  • 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

https://stackoverflow.com/questions/3337056/convenient-way-to-parse-incoming-multipart-form-data-parameters-in-a-servlet

 

Comments