스프링/4. 스프링 MVC-2

84. 파일 업로드

sdafdq 2023. 9. 24. 23:36

일반적으로 html Form의 post 방식으로 데이터를 전송하면, applicaation/x-www-form-urlencoded 방식으로 전송이 된다.

form 태그에 별도의 enctype 옵션이 없다면 자동으로 저 타입을 요청의 헤더 Content-Type: application/x-www-form-urlencoded 하고 추가한다.

 

그리고, 메시지 바디에 key1=value1&key2=value2..... 형태로 전송된다.

 

하지만, 이러 한 문자가 아니라 파일이라면,

파일은 바이너리 데이터를 전송해야 한다. 이 방식으로 파일을 전송하기는 어렵다.

또한, 폼 전송 시 파일을 전송 해도,  보통 파일만 보내지 않는다. 뭐 예를들어 회원이라면 회원 이미지(파일), 닉네임 등등...

 

위와 같은 이유 때문에, HTTP에서는 multipart/form-data라는 전송 방식을 제공한다.

 

html에서 form 태그에 enctype="multipart/form-data" 하고 추가하면 된다.

그렇게 하면,

이렇게 여러 파트로 폼 데이터가 나뉜다.

Content-Disposition: form-data; name="username"         (헤더)

kim         (바디)

 

Content-Disposition: form-data; name="age"       (헤더)

20          (바디)

 

이렇게 모든 데이터들이 헤더 , 바디 형식으로 나뉜다.

 

보면 파일 같은 경우는 추가로 파일이름, Content-Type(파일타입) 까지 추가로 들어가고,

바디 부분에는 바이너리 데이터가 들어간다.

 

html에서 form 태그에 enctype="multipart/form-data" 를 하면, 자동으로 요청메시지에 위처럼 들어가는 것이다.

----XXXX... 이거는 바운더리, 영역구분

 

 

 

@Slf4j
@Controller
@RequestMapping("/servlet/v1")
public class ServletUploadControllerV1 {
    @GetMapping("/upload")
    public String newFile(){
        return "upload-form";
    }

    @PostMapping("/upload")
    public String saveFileV1(HttpServletRequest request) throws ServletException, IOException {
        log.info("request={}",request);

        String itemName = request.getParameter("itemName");
        log.info("itemName={}", itemName);

        Collection<Part> parts = request.getParts();
        log.info("parts={}",parts);

        return "upload-form";
    }
}

 

 

<div class="container">
    <div class="py-5 text-center">
        <h2>상품 등록 폼</h2>
    </div>
    <h4 class="mb-3">상품 입력</h4>
    <form th:action method="post" enctype="multipart/form-data">
        <ul>
            <li>상품명 <input type="text" name="itemName"></li>
            <li>파일<input type="file" name="file" ></li>
        </ul>
        <input type="submit"/>
    </form>
</div>

 

 

이거는, application.properties에 

logging.level.org.apache.coyote.http11=debug

 

이거 적으면 찍히는 건데, 

 

보면은 위에 사진처럼 part로 나뉘어져 있다.

header, body....

 

 

또, application.properties에 유용한 옵션이 있는데,

spring.servlet.multipart.max-file-size = 1MB

이렇게 하면 파일 하나의 최대 크기는 1MB로 제한하는 거고 (기본이 1MB)

 

spring.servlet.multipart.max-request-size=10MB

이렇게 하면 요청의 최대 사이즈를 10MB로 제한하는 것이다.   (기본이 10MB)

 

위의 옵션을 사용하면, 사이즈를 넘길 시 SizeLimitExceededException 예외가 발생한다.

 

spring.servlet.multipart.enabled=false

이거는 스프링에서 멀티파트로 들어오는 것에 대한 처리를 하지 않는 다는 것이다. (application/x-www-form-urlencoded 만 지원할거다, 뭐 이런 의미로 저렇게 해 놓을 수도.)

그래서 컨트롤러에서 itemName, parts라던지 비어있는 걸로 찍힘. 처

 

여튼 기본이 true이고, 또 멀티파트로 들어오면 request도 StandardMultipartHttpServletRequest이다. 

false면 RequestFacade이다.

 

 

근데, MultipartHttpServletRequest는 잘 사용하지 않고, MultipartFile을 주로 사용한다. 더 편하다고 한다.