티스토리 뷰
(참고: Spring Boot와 Thymeleaf를 기준으로 작성된 글입니다)
HTML Form 전송 방식
HTML Form을 통한 파일 업로드를 이해하기 위해서는 두 가지 방식의 차이를 알아야 한다
• application/x-www-form-urlencoded
<form action="/save" method="post">
<input type="text" name="usernmae"/> //kim
<input type="text" name="age"/> //20
<button type="submit">전송</button>
</form>
application/x-www-form-urlencoded 방식은 HTML 폼 데이터를 서버로 전송하는 가장 기본적인 방법이다, Form 태그에 별도의 enctype옵션이 없다면 웹 브라우저는 요청 HTTP의 헤더에 다음과 같이 추가하여, 폼에 입력한 항목을 HTTP 바디와 함께 전송한다
POST/save HTTP/1.1
Host:localhost:8080
Content-Type:application/x-www-form-urlencoded
username=kim&age=20
하지만 파일을 업로드하려면 문자가 아닌 바이너리 데이터를 전송해야 하고, 파일뿐만 아니라 보통 폼을 전송할 때 파일과 함께 입력한 항목들을 같이 전송해야 한다는 문제점이 있다
• multipart/form-data
파일과 함께 항목을 같이 전송하기 위하여 HTTP는 multipart/form-data라는 전송 방식을 제공한다, multipart라는 이름처럼 다른 종류의 여러 파일과 폼의 내용을 '함께' 전송할 수 있다
<form action="/save" method="post" enctype="multipart/form-data">
<input type="text" name="usernmae"/> //kim
<input type="text" name="age"/> //20
<input type="file" name="file"/> //example.png
<button type="submit">전송</button>
</form>
위의 예시와 같이 enctype을 multipart/form-data로 지정하게 되면 여러 개의 파트로 나누어 각각의 전송 항목을 구분한다
POST/save HTTP/1.1
Host:localhost:8080
Content-Type:multipart/form-data,boundary=------XXX
-------XXX
Content-Disposition: form-data; name="username"
kim
-------XXX
Content-Disposition: form-data; name="age"
20
-------XXX
Content-Disposition: form-dta; name="file"; filename="example.png"
Content-Type: image/png
(바이너리 코드....)
-------XXX--
이렇게 multipart/form-data는 각각의 항목을 구분해서, 한 번에 전송하는 원리이다
MultipartFile
위에서 Form 통해 전송해온 파일들을 편리하게 받을 수 있게 스프링에서는 MultipartFille이라는 인터페이스를 지원한다
@Controller
public class FileController {
@PostMapping("/save")
public String saveFile(@RequestParam MultipartFile file) {
}
}
위의 예시처럼 @RequestParam을 업로드하는 HTML Form의 name에 맞추어 적용하면 되며, @ModelAttribute에서도 동일하게 사용할 수 있다, MultipartFile인터페이스의 주요 메서드는 아래와 같다
• file.getOriginalFileName() : 업로드 파일 명
• file.transferTo(...) : 파일 저장
UUID Filename + ExtendName
보통 클라이언트가 보내는 이미지 파일은 서버에서 UUID 등의 구분자를 부여하여 관리하게 된다, 그 이유는 만약 클라이언트 A가 올린 파일과 클라이언트 B가 올린 파일의 내용은 다르지만 이름이 같은 경우에 덮어쓰기가 되기 때문이다, 또한 확장자 파일명을 따로 붙여줘 더욱 편리하게 파일들을 관리할 수 있도록 해주는 것이 좋다고 한다
//메서드를 따로 만들어 공용으로 사용
private String extractExt(String originalFilename) {
int pos = originalFilename.lastIndexOf(".");
return originalFilename.substring(pos + 1);
}
private String createStoreFileName(String originalFilename) {
String ext = extractExt(originalFilename);
String uuid = UUID.randomUUID().toString();
return uuid + "." + ext;
}
핵심정리
클라이언트가 Form 통하여 파일을 보내는 경우, 보통 폼에 입력한 항목들을 같이 전송하기 때문에 MultipartForm을 사용하여 보내게 된다, 말 그대로 여러 파트로 구분하여 보내어지는데 스프링에서는 서버 측에서 편리하게 받을 수 있도록 MultipartFile이라는 인터페이스를 지원한다
서버에서 받게 된 파일은 UUID 등의 구분자를 통하여 중복되어 덮어 써지는 일을 방지하고 확장자명까지 추출해내어 추후에도 파일을 편리하게 관리하는 것이 좋다
개인 학습을 위해 작성되는 글입니다.
제가 잘못 알고 있는 점에 대한 지적 / 더 나은 방향에 대한 댓글을 환영합니다.
참조 링크:
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2/dashboard
'Spring > Spring MVC' 카테고리의 다른 글
[Spring MVC] TypeConverter & Formatter (0) | 2021.09.21 |
---|---|
[Spring MVC] API Error (API 오류 처리) (0) | 2021.09.17 |
[Spring MVC] Error Pages (오류 페이지) (0) | 2021.09.14 |
[Spring MVC] Filter & Interceptor (0) | 2021.09.10 |
[Spring MVC] Login with Cookie & Session (0) | 2021.09.09 |
- Total
- Today
- Yesterday
- cookie
- 제이쿼리 직접 선택자
- 캐시
- DefaultHandlerExceptionResolver
- Session
- maenco
- 쿠키
- jQuery 직접 선택자
- Spring MVC
- ExceptionHandlerExceptionResolver
- 세션
- 제이쿼리 탐색선택자
- Spring TypeConverter
- OOP
- http
- Spring API Error
- Cache
- 제이쿼리 기본 선택자
- 제이쿼리란
- Spring Container
- DTO와 VO의 차이
- application/x-www-form-urlencoded
- 맨코
- @ResponseStatus
- ResponseStatusExeceptionResolver
- 제이쿼리 인접 관계 선택자
- @ExceptionHandlere
- uri
- 제이쿼리 위치탐색선택자
- spring
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 27 | 28 | 29 | 30 | 31 |