서블릿 파일 업로드
V1
컨트롤러
@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";
}
}upload-form.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
</head>
<body>
<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> <!-- /container -->
</body>
</html>application.properties
logging.level.org.apache.coyote.http11=debug
# HTTP 요청 메시지를 확인할 수 있는 옵션실행해보면 로그에 multipart/form-data방식으로 전송이 됐다.
멀티파트 사용 옵션
spring.servlet.multipart.max-file-size=1MB spring.servlet.multipart.max-request-size=10MB용량이 큰 파일이 무제한 업로드 되는 것을 제한할 수 있다. 사이즈를 넘으면 예외(
SizeLimitExceedException)가 발생한다.
max-file-size: 파일 하나의 최대 사이즈, 기본 1MB
max-request-size: 요청 하나에 여러 파일들의 전체 합, 기본 10MB또
spring.servlet.multipart.enabled=false가 있다. 멀티파트는 일반적인 폼 요청(application/x-www-form-urlencoded)보다 훨씬 복잡하다. 이 옵션을 끄면 서블릿 컨테이너는 멀티파트와 관련된 처리를 하지 않는다. (default:true)
V2
이제 파일을 받아야 하는데 파일이 저장되는 경로가 필요하다.
application.properties
file.dir=C:/Users/User/file/컨트롤러
@Slf4j
@Controller
@RequestMapping("/servlet/v2")
public class ServletUploadControllerV2 {
@Value("${file.dir}")
private String fileDir;
@GetMapping("/upload")
public String newFile() {
return "upload-form";
}
@PostMapping("/upload")
public String saveFileV2(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";
}
}멀티파트 형식은 전송 데이터를 하나하나 각각 부분(Part)으로 나누어 전송하는데 parts에는 이렇게 나누어진 데이터가 각각 담긴다. 서블릿이 제공하는 Part는 멀티파트 형식을 편리하게 읽을 수 있는 다양한 메서드를 제공한다.
part.getSubmittedFileName(): 클라이언트가 전달한 파일명part.getInputStream(): Part의 전송 데이터를 읽을 수 있다.part.write(): Part를 통해 전송된 데이터를 저장할 수 있다.
Last updated