enctype="multipart/form-data"
라고 명시해야 한다. <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>
httpRequest 의 로그를 보기 위해서 다음으로 설정해야 한다.
logging.level.org.apache.coyote.http11=debug
다음 설정은 한 파일당 크기 제한과 한 요청당 크기 제한을 설정하는 것이다.
spring.servlet.multipart.max-file-size=1MB
spring.servlet.multipart.max-request-size=10MB
다음과 같이 설정하면 기존 default request 구현체 였던 RequestFacade를 사용하도록 강제해 multipart 와 관련된 처리를 하지 않게끔 한다.
spring.servlet.multipart.enabled=false
multipart-form 을 쓰게 되면 StandardMultipartHttpServletRequest
구현체가 사용된다. 따라서 옵션을 true로 설정해 스프링부트가 서블릿 컨테이너에게 멀티파트 데이터를 처리하라고 지시해야한다.
서블릿 컨테이너에서 멀티파트 리졸버를 실행해 일반적인 HttpServletRequest
를 MultipartHttpServletRequest
로 변환해서 반환한다.
MultipartHttpServletRequest
는 HttpServletRequest
의 자식 인터페이스이고, 멀티파트와 관련된 추가 기능을 제공한다.
properties 파일 읽기
@Value("${file.dir}")
private String fileDir;
스프링에서 제공하는 @Value를 이용하자
multipartpart 요청의 경우 각 파트에도 header와 body로 구성되어 있다.
@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);
for (Part part : parts) {
log.info("==== PART ====");
log.info("name={}", part.getName());
Collection<String> headerNames = part.getHeaderNames();
for (String headerName : headerNames) {
log.info("header {}:{}", headerName, part.getHeader(headerName));
}
log.info("submittedFileName = {}", part.getSubmittedFileName());
log.info("size={}", part.getSize());
InputStream inputStream = part.getInputStream();
String body = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("body={}", body);
if (StringUtils.hasText(part.getSubmittedFileName())) {
String fullPath = fileDir + part.getSubmittedFileName();
log.info("파일 저장 fullPath = {}", fullPath);
part.write(fullPath);
}
}
return "upload-form";
}
request=org.springframework.web.multipart.support.StandardMultipartHttpServletRequest@1b225a15
itemName=Spring
parts=[org.apache.catalina.core.ApplicationPart@2eec8a8b, org.apache.catalina.core.ApplicationPart@4f37b7aa]
==== PART ====
name=itemName
header content-disposition:form-data; name="itemName"
submittedFileName = null
size=6
body=Spring
==== PART ====
name=file
header content-disposition:form-data; name="file"; filename="스크린샷 2022-07-12 오후 10.37.26.png"
header content-type:image/png
submittedFileName = 스크린샷 2022-07-12 오후 10.37.26.png
size=32789
body=�PNG ....
파일 저장 fullPath = /Users/MYNAME/Desktop/김영한-스프링/스프링 MVC - 2/스크린샷 2022-07-12 오후 10.37.26.png
위 로그에서 볼 수 있듯이 2개의 파트로 구성되어 있는 요청을 볼 수 있다.
해당 part가 파일인지 판단은 getSubmittedFileName!=null
로 간단하게 했다.
part는 쉽게 파일을 저장할 수 있게 write() 메서드도 제공한다.