스프링/MVC

[MVC 기초] Spring Boot File Upload/Download 구현하기 (+ multipart/form-data 설명)

nomoreFt 2022. 7. 26. 20:48

Spring Boot 파일 Upload Form 구현하기

form 데이터는 2가지로 구분된다.

  1. application/x-www-form-urlencoded
  2. multipart/form-data

여기서 application/x-www-form-urlencoded 는 일반적인 key-value 의 form 데이터 전송을 담당하고,

파일과 다양한 정보들을 함께 넘겨야 하기 때문에 multipart/form-data를 사용한다.

multipart-form

form에서 enctype으로 multipart라고 명시한다.

<form action="/test" method="post" enctype="multipart/form-data">
    ...
</form>
  • enctype="multipart/form-data" : 멀티파트로 form 데이터를 넘긴다는 뜻

multipart-form 예제

Request Header

POST / HTTP/1.1
Host: localhost:8000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:29.0) Gecko/20100101 Firefox/29.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: __atuvc=34%7C7; permanent=0; _gitlab_session=226ad8a0be43681acf38c2fab9497240; __profilin=p%3Dt; request_method=GET
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266
Content-Length: 554

-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="text"

text default
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain

Content of a.txt.

-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html

<!DOCTYPE html><title>Content of a.html.</title>

-----------------------------9051914041544843365972754266--
  • Accept-Encoding: gzip, deflate : 클라이언트 -> 웹서버에게 gzip 압축을 이해하고 해제할 수 있다고 서버에 알리는 것이다. (명시)

Response Header

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html
Content-Encoding: gzip
Server: GWS/2.1
Content-Length: 1865
Date: Thu, 14 Jul 2005 14:21:24 GMT

Response에서 결과물을 Content-Encoding: gzip 이런 식으로 서버 -> 클라이언트로 보내는 내용이 gzip 암호화 되어있다고 표기한다.

  • multipart/form-data는 다른 여러 종류의 파일과 폼의 내용을 함께 전송 할 수 있다.

    1. 기본 text인 key-value

      -----------------------------9051914041544843365972754266
      Content-Disposition: form-data; name="text"
      
      text default
    2. text file과 html

      -----------------------------9051914041544843365972754266
      Content-Disposition: form-data; name="file1"; filename="a.txt"
      Content-Type: text/plain
      
      Content of a.txt.
      
      -----------------------------9051914041544843365972754266
      Content-Disposition: form-data; name="file2"; filename="a.html"
      Content-Type: text/html

multi-part 업로드 파일 사이즈 제한

spring.servlet.multipart.max-file-size=1MB
spring.servlet.multipart.max-request-size=10MB
  • max-file-size : 개별 파일 사이즈 제한
  • max-request-size : 한 Request 전체 파일 사이즈 제한

💥참고로 서버의 multipartForm 사용을 안한다고 끄는 기능도 있다.

실습

Upload

실제 경로 설정

  1. Upload가 되려면 저장공간이 필요하기 때문에, 실제 파일저장 경로를 설정해주어야 한다.

yml 파일

file.dir=/Users/study/file/

💥마지막에 /가 들어감

  1. Controller에서 기본 file경로를 설정해준다.
public class ServletUploadControllerV2 {

  @Value("${file.dir}")
  private String fileDir;
}
  • @Value("${file.dir}") : properties, yml 등의 설정을 가져다 쓰는 방법

Front의 Form에서 multiPartForm으로 itemName,file을 보낸 상황


    @PostMapping("/upload")
    public String saveFile(@RequestParam String itemName,
                           @RequestParam MultipartFile file, HttpServletRequest request) throws IOException {

        log.info("request={}", request);
        log.info("itemName={}", itemName);
        log.info("multipartFile={}", file);

        if (!file.isEmpty()) {
            String fullPath = fileDir + file.getOriginalFilename();
            log.info("파일 저장 fullPath={}", fullPath);
            file.transferTo(new File(fullPath));
        }

        return "upload-form";
    }
  • @RequestParam String itemName : Request의 itemName을 받는다.
  • @RequestParam MultipartFile file : Spring에서 지원하는 MultipartFile 인터페이스로 file들을 받을 수 있다.
    • file.getOriginalFilename() : file의 이름을 반환해준다. 이름 그대로 저장하는 경로 설정에 사용
    • file.transferTo : 실 파일 저장

💥 운영에서는 보통 db서버에 blob로 저장하여 db에 저장해둔다.