파일 업로드
는 일반적으로 HTML Form을 통해 이루어진다. HTML Form 전송 방식에는 두 가지가 있다.
application/x-www-form-urlencoded
파일을 업로드하려면 문자가 아니라 binary 데이터를 전송해야 하는데, 문자를 전송하는 이 방식으로는 파일 전송이 어렵다.
이 문제를 해결하기 위해 HTTP는 multipart/form-data 방식을 제공한다.
multipart/form-data
enctype="multipart/form-data"
를 지정해줘야 한다.username=gildong&age=10
형태로 데이터를 보내는 application/x-www-form-urlencoded 방식과 달리, 각 데이터마다 별도의 헤더와 바디값을 가지고 있는 것을 확인할 수 있다.
파일의 경우
파일 이름(filename)과 Content-Type (image/png) 이 추가되고, binary 데이터가 전송된다.
Spring은
MultipartFile
이라는 인터페이스로 multipart 파일의 업로드와 다운로드를 매우 편리하게 지원해준다.
@Value("${file.dir}")
: 파일을 저장할 경로를 설정 파일에 지정한다.
ex) /Users/kim/...
MultipartFile
인터페이스를 사용해 손쉽게 데이터를 받을 수 있다.
file.getOriginalFilename()
: 업로드 파일 명file.transferTo()
: 파일 저장
상품을 저장할 때 상품의 이름과 함께 첨부파일과 이미지 파일을 저장해야 하는 경우
상품 저장 요청을 받는 폼
단일 첨부파일을 받는 attachFile과 다중 이미지 파일을 받는 imageFiles가 있다.
다중 파일을 업로드하려면 html 태그에
multiple="multiple"
옵션을 주면 된다.
사용자가 업로드한 파일명과 서버에 저장할 파일명을 구분하는 이유는 서로 다른 사용자가 같은 파일이름을 업로드 하는 경우 충돌이 날 수 있기 때문이다.
서버에서는 저장할 파일명이 겹치지 않도록 내부에서 관리하는 별도의 파일명이 필요
하다.
createStoreFileName()
: 서버 내부에서 관리하는 파일명으로 UUID 를 사용했다.
extractExt()
: 확장자를 별도로 추출해서 서버 내부에서 관리하는 파일명에도 붙여준다.
예를 들어, 고객이 a.png 라는 이름으로 업로드 하면
51041c62-86e4-4274-801d-614a7d994edb.png
와 같이 UUID에 확장자를 붙여 저장한다
ItemForm 의 형식으로 multipart 데이터를 받아온다.
fileStore.storeFile(), fileStore.storeFiles
파일을 서버에 저장한 후, 해당 파일의 이름을 필드로 가지고 있는 UploadFile의 형태로 반환하여 item으로 넘기고 해당 item을 저장한다.
자료 출처 : 김영한 님의 Spring MVC 2편