Multipart를 잘 이해하기 위해서는 HTTP 통신에 대한 선행 지식이 있어야 합니다.
Input
엘리먼트에서 enctype
으로 이용된다.enctype
은 application/x-www-form-urlencoded
이다.text-plain
도 있긴 한데 잘 쓰이진 않는다.application/x-www-form-urlencoded
enctype
은 큰 용량의 데이터를 전송하기엔 적합하지 않다.POST /cgi-bin/qtest HTTP/1.1
Host: aram
User-Agent: Mozilla/5.0 Gecko/2009042316 Firefox/3.0.10
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
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://aram/~martind/banner.htm
Content-Type: multipart/form-data; boundary=2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Length: 514
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile1"; filename="r.gif"
Content-Type: image/gif
GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile2"; filename="g.gif"
Content-Type: image/gif
GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile3"; filename="b.gif"
Content-Type: image/gif
GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f--
위는 Multipart HTTP 요청의 예시이다. 일반적인 HTTP 요청과 비슷한 형태를 띄지만, 약간 다른 점이 있다.
POST
를 사용한다.Content-Type
이 multipart/form-data
이다.boundary
라는 것이 존재하여 각 엔티티를 나눈다.\r\n
을 개행(CRLF)으로 사용해준다.boundary
로 나누어진 각 부분을 content-transfer-encoding
헤더에 정의된대로 인코딩할 수도 있다.key/value
쌍을 구분하기 위해서 boundary
를 이용한다.boundary
가 사용되었다.boundary
는 1~70자의 문자들로 --
로 시작하여 --
로 끝난다.boundary
로 나누어 각 데이터들을 읽는다.
boundary
로 나뉘어 여러 엔티티가 전송되기 때문에Multipart
라는 이름을 쓰는 것 같다. (추측)
보안이나 운영상 이슈 때문에 보통은 기본 파일 첨부 사이즈가 제한되어 있다. 이것 때문에 헷갈려 하는 분들이 많다.
일반적으로 사용하는 WAS인 톰캣의 경우, 자동으로 FileSize에 제한이 걸려있는데, 아래와 같은 설정을 통해 풀어줄 수 있다.
209715200
은 200MB정도의 크기이다.
<servlet>
...
<multipart-config>
<file-size-threshold>0</file-size-threshold>
<max-file-size>209715200</max-file-size>
<max-request-size>209715200</max-request-size>
</multipart-config>
...
</servlet>
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxSwallowSize = "-1"/>
@Bean
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver resolver=new CommonsMultipartResolver();
resolver.setMaxUploadSize(15728640);
resolver.setMaxUploadSizePerFile(15728640);
return resolver;
}
# 첨부파일 관련 설정
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
@WebServlet("/uploadFiles")
@MultipartConfig( fileSizeThreshold = 0, maxFileSize = 209715200, maxRequestSize = 209715200)
public class FileUploadServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) {
// ...
}
}
우리가 일반적으로 사용하는 WAS인 톰캣의 경우 Post의 길이 제한은 2MB로 설정되어 있다.
톰캣의 web.xml
에 접근하면 아래와 같이 maxPostSize
를 설정하는 항목이 있고, 이를 "0"
으로 바꾸면 무제한의 용량을 서버가 받을 수 있게 된다. (톰캣 버전 7.0.63 미만에서는 0
이 무제한을 의미하며, 그 이상 버전에서는 -1
이 무제한을 의미한다고 한다.) 기본 값은 2097152 (2 megabytes)
이다.
<!-- Define a Coyote/JK2 AJP 1.3 Connector on port 8009 -->
<Connector port="8009"
enableLookups="false" redirectPort="8443" debug="0"
protocol="AJP/1.3" maxPostSize="0"/>
<!-- 0는 무제한을 의미한다. -->
이렇게 설정된 데는 다 이유가 있다. 만일 이렇게 용량 제한을 걸지 않으면, 서버를 폭파시킬 목적으로 해커가 어마어마하게 큰 요청을 계속 보내도 서버는 꾸역꾸역 처리하게 되고, 이 과정에서 과부하가 일어나서 서버가 폭발할 수 있다. 그러므로 이 제한을 해제할 때는 반드시 이러한 보안 이슈가 일어날 수 있다는 점을 감안하자. 또한, 한번에 무제한으로 늘리지 말고 필요한 만큼 조금씩 늘려가자.
멀티파트 요청이란?
멀티파트의 형태
멀티파트에서 boundary란
스프링에서 멀티파트를 처리하는 방법
Mozilla Content-Type
RFC1341
forms
Multipart 구성방법
멀티파트를 이용한 업로드