06 MultipartFile
06 MultipartFile
1. MultipartFile
1. MultipartFile
- MultipartFile은 스프링 프레임워크가 제공하는 인터페이스
- HTTP multipart/form-data 요청으로 업로드된 파일을 스프링이 편하게 다루도록 감싼 추상화 객체
- package :
org.springframework.web.multipart.MultipartFile
2. 주요메서드
1
2
3
4
5
6
7
8
String getName(); // 폼 필드 이름
String getOriginalFilename(); // 클라이언트가 보낸 원래 파일명
String getContentType(); // Content-Type 헤더 (ex: image/png)
boolean isEmpty(); // 파일이 비어있는지
long getSize(); // 바이트 단위 크기
byte[] getBytes() throws IOException;
InputStream getInputStream() throws IOException;
void transferTo(File dest) throws IOException, IllegalStateException;
3. MultipartFile이 생성되는 흐름
- 클라이언트가 multipart/form-data로 요청 전송
- DispatcherServlet → MultipartResolver가 요청 파싱
- MultipartResolver가 MultipartFile 구현체(예: StandardMultipartFile, CommonsMultipartFile)를 생성
- 컨트롤러 파라미터로 주입
2. 예시
1. 단일 파일
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@PostMapping("/upload")
public ResponseEntity<String> upload(@RequestParam("file") MultipartFile file) throws IOException {
if (file.isEmpty()) {
return ResponseEntity.badRequest().body("empty");
}
String original = file.getOriginalFilename();
long size = file.getSize();
String contentType = file.getContentType();
Path target = Paths.get("/data/uploads", UUID.randomUUID() + "-" + sanitize(original));
file.transferTo(target.toFile());
return ResponseEntity.ok("saved");
}
2. 다중파일
1
2
3
4
5
6
7
@PostMapping("/multi")
public ResponseEntity<?> multi(@RequestParam("files") MultipartFile[] files) {
for (MultipartFile file : files) {
// 각 파일 검증 및 저장
}
return ResponseEntity.ok("ok");
}
3. 검증
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 확장자 검사
String originalName = file.getOriginalFilename(); //getName은 폼필드이름이 나옴
String ext = originalName.substring(originalName.lastIndexOf('.') + 1).toLowerCase();
List<String> allowedExt = List.of("jpg", "jpeg", "png", "pdf");
if (!allowedExt.contains(ext)) {
throw new IllegalArgumentException("허용되지 않은 확장자");
}
// Mime 타입검증
String mimeType = file.getContentType();
List<String> allowedMime = List.of("image/jpeg", "image/png", "application/pdf" );
if (!allowedMime.contains(mimeType)) {
throw new IllegalArgumentException("허용되지 않은 MIME 타입");
}
// 파일 사이즈 검증
long max = 5L * 1024 * 1024; // 5MB
if (file.getSize() > max) {
throw new MyFileTooLargeException();
}
- MIME 타입
- 브라우저나 서버가 “이 파일이 어떤 종류인지” 구분하기 위해 붙여주는 공식적인 콘텐츠 형식 이름
- 요청헤더에
Content-Type: image/png요렇게 들어옴. - virus.jpg.exe → 확장자를 jpg로 위장 가능하지만 MIME 타입은 내부 구조 기반으로 매핑돼서 위장하기 훨씬 어려움.
- 종류
1 2 3 4 5
image/jpeg → jpg, jpeg 이미지 image/png → png 이미지 application/pdf → pdf 문서 text/plain → txt 파일 application/zip → zip 압축파일
3.note
1. 컨트롤러는 단일인데, 파일은 다중이면
- 파일 내역
1 2 3
Content-Disposition: form-data; name="file"; filename="a.png" Content-Disposition: form-data; name="file"; filename="b.png" Content-Disposition: form-data; name="file"; filename="c.png"
- 컨트롤러
1 2 3 4 5
@PostMapping("/upload") public String upload(@RequestParam("file") MultipartFile file) { System.out.println(file.getOriginalFilename()); return "ok"; } - 업로드 파일
- 업로드 대상
- 파라미터가 MultipartFile이면 → 가장 첫 번째 part 한 개만 넣음
- 파라미터가 MultipartFile[] 또는 List
이면 → 모두 넣음
- 따라서 가장처음 a.png만 들어옴
- 업로드 대상
This post is licensed under CC BY 4.0 by the author.