티스토리 뷰

반응형

(참고: 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

 

반응형
댓글