MultipartFile 파일 업로드

JP·2022년 1월 16일
0

spring

목록 보기
4/5

Mutlipart/form-data

HTML에서는 파일 업로드를 위한 폼 전송방식에는 두가지 방식이 있다
1. application/x-www-form-urlencoded
2. multipart/form-data

1번은 말 그대로 url에 form을 인코딩해서 넘기는 방식이다.
문제는 우리는 폼 전송을 할 때 파일만 전송하는 경우가 거의 없이 다른 입력값들과 함께 보내야 하는 경우가 있다
예를 들어, 이름, 나이 , 프로필 사진 등 과 같은 형식의 폼 말이다.
url-encoded 방식을 사용한다면 파일의 바이너리코드들을 url에 넘겨야 하는데 이렇게 하면 url주소가 길어질뿐더러
우리가 폼과 함께 보내는 일반 문자와 바이너리 코드들을 동시에 전송해야 하는 문제점이 생긴다.

이를 해결하기 위해 multipart/form-data 가 존재한다. 이를 사용하기 위해 enctype="muiltipart/form-data" 를 추가해준다.

<form th:action method="post" enctype="multipart/form-data">
  ...
  ...
  ...
</form>

multipart/form-data를 사용해서 폼을 넘긴다면 다음과 같이 HTTP가 입력 폼을 전달 받게 된다

Received [------WebKitFormBoundaryxcfRwtsJTTnVQ8NJ
Content-Disposition: form-data; name="사진이름"

사진1
------WebKitFormBoundaryxcfRwtsJTTnVQ8NJ
Content-Disposition: form-data; name="file"; filename="öÍ(Ô'©G.png"
Content-Type: image/png

çƒž}j˜Ó#gÆ'#úPßV]=X³éJ‘ò£ 
’?Sުɣ)Ú~ñ=²8'ëSÍr夊‡N»öýó€Þþ´«£N#ïÈÝØgëè}
ªã¸8Ý_¨Äïc×'¥O¬Ò±.üdëéõÅk¿1Òk©F9úX5LM—
..
..
------WebKitFormBoundaryxcfRwtsJTTnVQ8NJ--

multipart/form-data를 스프링에서는 어떻게 사용할 수 있을까?

Servlet 방식

인자값으로 HttpServletRequest을 넘긴다면 그 속에 우리가 원하는 파라미터와 파일들까지 모두 얻을 수 있다.

@PostMapping(value = "/upload")
    public String upload(HttpServletRequest request) throws IOException, ServletException {
        String itemName = request.getParameter("itemName");
        Collection<Part> parts = request.getParts();

        return "upload-form";
    }

다음과 같이 request에서 parts의 collection을 뽑아낼 수 있다.
Collection<Part>에는
header
submittedFileName
size
등의 정보를 알 수 있는 메서드들이 존재한다.

spring의 설정 옵션 중 spring.servlet.multipart.enabled라는 옵션이 있다. (디폴트값 true)
이 옵션을 켜주면 HTML에서 enctype="multipart/form-data" 로 넘어오는 요청의 경우
서블릿 컨테이너가 HttpServletRequestMultipartHttpServletRequest로 변환해서 반환해준다!
MultipartHttpServletRequestHttpServletRequest 의 자식 인터페이스고 관련된 추가 기능을 사용할 수 있다.

@PostMapping(value = "/upload")
    public String upload(MultipartHttpServletRequest request) throws IOException, ServletException {
        String itemName = request.getParameter("itemName");
        Collection<Part> parts = request.getParts();

        return "upload-form";
    }

하지만 이 MultipartHttpServletRequest는 스프링에서 제공해주는 MultipartFile 인터페이스때문에 거의 사용하지 않는다.

MultipartFile

HttpServletRequest에서 Part를 request에서 뽑아서 사용하기에 불편한 점이 있는데 이를 스프링은 MultipartFile이라는 인터페이스를 통해 매우 편리하게 지원해준다.

시작하기 앞서 실제 파일이 저장 될 경로를 만들어주고 이를 application.properties에 지정해준다

# application.properties 마지막에 '/' 가 들어간다. 
file.dir=D:/fileUploadExample/uploadfile/
@Value("${file.dir}")
private String fileDir;

@PostMapping(value="/upload")
    public String saveFile(@RequestParam MultipartFile file) throws IllegalStateException, IOException {
        if(!file.isEmpty()){
            String fullPath = fileDir + file.getOriginalFilename();
            log.info("파일 저장 fullPath = {}", fullPath);
            file.transferTo(new File(fullPath));
        }

        return "upload-form";
    }

위의 로직을 실행하면 앞서 지정해놓은 폴더에 업로드 한 파일이 올라가는 것을 확인할 수 있다.


https://github.com/JPWon-1/image-upload-kotlin/tree/master

profile
to Infinity and b

0개의 댓글