[SpringMVC] 파일 업로드
※ 파일 전송에서의 기본 인코딩 방식
서버와 클라이언트는 기본 인코딩 방식으로 application/x-www-form-urlencoded 을 사용한다.
이는 문자열만을 주고받는 방식으로 위 이미지에서 처럼
클라이언트가 uid를 newlec, name을 dragon으로 서버로 전송할 경우
uid=newlec&name=dragon로 문자열을 전송한다.
하지만 파일과 같은 바이너리 파일들은 이런 문자열 형태로는 전송하기가 어려운데,
이를 극복하기 위해 나온 것이 multipart/form-data 인코딩 방식이다.
위 이미지처럼 하나의 문자열이 아닌 각 name마다 데이터별 별개의 구분을 주어 전송한다.
따라서 우리가 서버를 작성할 때, 파일을 받기 위해서는 multipart/form-data 인코딩 방식의 송수신을 할 수 있도록 설정을 별도로 해줘야한다.
1. xml 파일에 multipart/form-data 인코딩을 위한 bean 객체 작성
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="314572800"/>
</bean>
maxUploadSize는 업로드 할 수있는 최대 파일의 크기를 설정하는 것으로,
314,572,800KB=300*1024*1024 KB(300MB)를 전송할 수 있도록 하였다.
(multipart/form-data bean 객체 작성시 property 설정과 관련해 더 알고싶다면 아래 링크를 참고하자.)
CommonsMultipartResolver (Spring Framework)
Set the default character encoding to use for parsing requests, to be applied to headers of individual parts and to form fields. Default is ISO-8859-1, according to the Servlet spec. If the request specifies a character encoding itself, the request encodin
docs.spring.io
2. form 태그에서 인코딩 방식 설정
<form action="reg" method="post" enctype="multipart/form-data">
...
...
</form>
인코딩 기본 설정은 application/x-www-form-urlencoded이기 때문에 위처럼 인코딩 방식을 따로 설정해줘야한다.
3. Dependncy 설정
파일업로드에 필요한 라이브러리 사용을 위해 Maven을 통해 Dependency를 설정해준다.
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
아래 링크에 해당 라이브러리 메이븐 레포지터리를 첨부한다.
- Apache Commons FileUpload
https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
4. 코드 작성
1) jsp 파일
<form action="reg" method="post" enctype="multipart/form-data">
<div class="margin-top first">
<h3 class="hidden">공지사항 입력</h3>
<table class="table">
<tbody>
...
<tr>
<th>첨부파일</th>
<td colspan="3" class="text-align-left text-indent"><input type="file"
name="files" /> </td>
</tr>
<tr>
<th>첨부파일</th>
<td colspan="3" class="text-align-left text-indent"><input type="file"
name="files" /> </td>
</tr>
...
</tbody>
</table>
</div>
<div class="margin-top text-align-center">
<input class="btn-text btn-default" type="submit" value="등록" />
<a class="btn-text btn-cancel" href="list.html">취소</a>
</div>
</form>
첨부파일 2개의 name을 files로 통일했다. 따라서 전송시 배열형태로 서버로 전송한다.
2) java 파일
@RequestMapping("reg")
@ResponseBody
public String reg(MultipartFile[] files, HttpServletRequest request) throws IllegalStateException, IOException {
for(MultipartFile file : files) { // 파일을 배열에서 하나씩 받아옴
long size=file.getSize(); // 파일 사이즈 받아옴
String fileName=file.getOriginalFilename(); // 파일 이름 받아옴
ServletContext ctx=request.getServletContext();
String webPath="/static/upload"; // 홈 디렉터리에서부터 파일 설치할 폴더까지의 경로
String realPath=ctx.getRealPath(webPath); // ServletContext를 통해 절대경로를 받아옴
//realPath에 해당 폴더가 존재하지 않으면 경로상 모든 디렉터리 생성해줌
File savePath = new File(realPath);
if(!savePath.exists())
savePath.mkdirs();
realPath+=File.separator+fileName; // 저장할 폴더까지의 절대경로 + 구분자 + 파일명
File saveFile = new File(realPath); // os에 마다 구분자가 다르므로 File.separator 사용이 바람직
file.transferTo(saveFile); // 해당 경로에 파일 저장
}
}
위와 같이 설정 후 코드를 작성하면, 첨부파일을 n개 이상 첨부할 수 있는 다중 파일 업로드가 가능하다.
※주의해야할 점
실제로 파일이 저장되는 경로는 위에서 구한 절대경로가 아니다.위에서 구한 경로인 (자신의 프로젝트 폴더)\webprj\src\main\webapp\static 가 아닌(자신의 프로젝트 폴더)\.metadata\.plugins\org.eclipse.wst\server.core\tmp0\wtpwebapps\webprj\static\upload에 저장이 된다.