개요
HTML 폼 전송 방식
- application/x-www-form-urlencoded
- multipart/form-data
일판 폼 방식으로 data를 전송하면 Content-Type 헤더에 application/x-www-form-urlencoded 간다
해당 헤더는 문자를 통해 폼 데이터를 전송한다
그런데 파일은 문자가 아니라 바이너리 데이터를 전송해야 한다.
그리고 한 가지 문제가 또 있는데 보통 폼을 전송할 때 파일만 전송하는 게 아니라 문자도 같이 전송한다
즉 이름, 나이는 문자로 전송하고 첨부파일은 바이너리로 전송해야 한다
multipart/form-data

multipart/form-data 방식은 다른 종류의 여러 파일과 폼의 내용 함께 전송할 수 있다
폼의 입력 결과로 생성된 HTTP Message를 보면 각각의 항목이 구분되어 있다
특히 Content-Disposition이라는 항목별 헤더가 추가되어 있고 부가 정보가 담겨 있다
username, age, file1 이 각각 파트라는 이름으로 분리되어 있고
각 파트는 HTTP Message처럼 헤더와 바디로 또 나뉜다
폼의 일반 데이터는 각 항목별로 문자가 전송되고 파일의 경우 파일 이름과 Content-Type 이 추가되고 바이너리 데이터가 전송된다
멀티파트 사용 옵션 (Servlet)
이전까지 블로그를 썼던 것처럼 스프링이 제공하는 기술을 바로 가는 것보단 Servlet 이 어떻게 동작하는지부터 찾아가 보자
서블릿은 이러한 멀티파트 특히 파일업로드 다운로드에 관하여 다양한 기술을 이미 제공하고 있었다
1. 업로드 사이즈 제한
spring.servlet.multipart.max-file-size=1MB
spring.servlet.multipart.max-request-size=10MB
2. spring.servlet.multipart.enabled
→ 멀티파티 관련 예외를 해라 말아라 하는 옵션
끄게 되면
request=org.apache.catalina.connector.RequestFacade@xxx
itemName=null
parts=[]
spring.servlet.multipart.enabled 옵션을 끄면 서블릿 컨테이너는 멀티파트와 관련된 처리를 하지 않는다
그래서 결과 로그를 보면 request.getParameter("itemName") , request.getParts()의 결과가 비어있다
옵션 켜기
request=org.springframework.web.multipart.support.StandardMultipartHttpServlet
Request
itemName=Spring
parts=[ApplicationPart1, ApplicationPart2]
spring.servlet.multipart.enabled=true (기본 true) 이 옵션을 켜면, 스프링 부트는 서블릿 컨테이너에게 멀티파트 데이터를 처리하라고 설정한다. (참고로 기본 값은 true이다)
request.getParameter("itemName")의 결과도 잘 출력되고, request.getParts()에도 요청한 두 가지 멀티파트의 부분 데이터가 포함된 것을 확인할 수 있다. 이 옵션을 켜면 복잡한 멀티파트 요청을 처리해서 사용할 수 있게 제공한다.
파일 저장하기
파일을 업로드하려면 해당 파일이 실제 저장되는 경로가 필요하다
저장되는 경로를 설정하고 싶으면 아래와 같이 application.properties에서 지정해 주면 된다
application.properties
file.dir=파일 업로드 경로 설정
(예): /Users/kimyounghan/study/file/
예시
@Value("${file.dir}")
private String fileDir;
@PostMapping("/upload")
public String saveFileV1(HttpServletRequest request) throws ServletException, IOException
Collection<Part> parts = request.getParts();
for (Part part : parts) {
//편의 메서드
//content-disposition ; filename ;
log.info("sumittedFilename={}",part.getSubmittedFileName());
log.info("size={}", part.getSize());
//데이터 읽기
InputStream inputStream = part.getInputStream();
String body = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
//파일에 저장하기
if(StringUtils.hasText(part.getSubmittedFileName())){
String fullPath = fileDir + part.getSubmittedFileName();
log.info("파일 저장 fullpath={}", fullPath);
part.write(fullPath);
}
return "upload-form";
}
서블릿으로 파일 업로드를 구현하려면 request.part를 통해서 Multipart에 있는 모든 part들을 꺼낸다
그 후 메서드를 통해 파일 업로드를 구현하면 된다 위에서 쓰인 메서드는 다음과 같다
Part 주요 메서드
part.getSubmittedFileName() : 클라이언트가 전달한 파일명
part.getInputStream(): Part의 전송 데이터를 읽을 수 있다
part.write(…) : Part를 통해 전송된 데이터를 저장할 수 있다
스프링 파일 업로드
서블릿이 제공하는 Part가 편하긴 하다
근데 HtpServletRequest를 사용해야 하고 여러 파트 중에 파일 파트를 구분하려면 이런저런 코드를 넣어야 한다
이제는 스프링이 제공하는 파일업로드를 알아보자
@PostMapping("/upload")
public String saveFile(@RequestParam String itemName,
@RequestParam MultipartFile file) throws IOException {
if (!file.isEmpty()) {
String fullPath = fileDir + file.getOriginalFilename();
log.info("파일 저장 fullPath ={}", fullPath);
file.transferTo(new File(fullPath));
}
}
스프링은 MultipartFile이라는 Class를 제공해 사용자가 편하게 file을 가져올 수 있게 한다
이를 @RequestParam과 같이 쓰고 스프링이 제공하는 편의 메서드를 사용하여 파일을 업로드하고 저장할 수 있다
주요 메서드
- file.getOriginalFilename() : 업로드 파일 명
- file.transferTo(…) : 파일 저장
'🌿 스프링 > 스프링 MVC 2편' 카테고리의 다른 글
| API 예외처리 (0) | 2026.02.15 |
|---|---|
| 서블릿 예외 처리와 오류 페이지 (0) | 2026.02.15 |
| 서블릿 필터와 스블릿 인터셉터 (0) | 2026.02.15 |
| 로그인 처리- 쿠키,세션 (0) | 2026.02.14 |
| Validation (0) | 2026.02.14 |