[Spring] 파일업로드 처리


파일 업로드 처리


인코딩 타입이 Multipart인 경우 파라미터나 업로드한 파일을 구하려면 전송 데이터를 알맞게 처리해 주어야 한다.

스프링은 Multipart 지원 기능을 제공하고 있기 때문에, 이 기능을 이용하면 추가적인 처리없이 Multipart 형식으로 전송된 파라미터와 파일 정보를 쉽게 구할 수 있다.


1. MultipartResolver 설정

Multipart 지원 기능을 이용하려면 먼저 MultipartResolver를 스프링 설정 파일에 등록해 주어야 한다. MultipartResolver는 Multipart 형식으로 데이터가 전송된 경우, 해당 데이터를 스프링 MVC에서 사용할 수 있도록

변환해준다. 예를 들어, @PathVariable 어노테이션을 이용해서 Multipart로 전송된 파라미터와 파일을 사용할 수 있도록 해준다.


스프링이 기본으로 제공하는 MultipartResolver는 CommmnosMultipartResolver이다. CommmnsMultipartResolver는 Commons FileUpload API를 이용해서 Multipart를 처리해준다.

CommmonsMultipartResolver를 MultipartResolver로 사용하려면 다음과 같이 빈 이름으로 "multipartResolver"를 사용해서 등록하면 된다.


<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

cf.) DispatcherServlet은 이름이 "multipartResolver"인 빈을 사용하기 때문에 다른 이름을 지정할 경우 MultipartResolver로 사용되지 않는다.


※ CommonsMultipartResolver 클래스의 프로퍼티

 프로퍼티

 타입

설명 

 maxUploadSize

 long

 최대 업로드 가능한 바이트 크기, -1은 제한이 없음을 의미한다. 기본 값은 -1이다.

 maxInMemorysize

 int 

 디스크에 임시 파일을 생성하기 전에 메모리에 보관할 수 있는 최대 바이트 크기, 

 기본 값은 10240 바이트이다.

 defaultEncording

 String 

 요청을 파싱할 때 사용할 캐릭터 인코딩, 지정하지 않은 경  우 HttpServletRequest.setEncording() 메서드로 지정한 캐릭터 셋이 사용된다. 

 아무 값도 없을 경우 ISO-8859-1을 사용한다.


2. @RequestParam 어노테이션을 이용한 업로드 파일 접근

업로드한 파일을 전달받는 첫 번째 방법은 @RequestParam 어노테이션이 적용된 MultipartFile 타입의 파라미터를 사용하는 것이다. 예를 들어, HTML 입력폼이 다음과 같이 작성되어 있다고 해보자

<form action="submitReport1.do" method="post" enctype="multipart/form-data">

학번: <input type="text" name="studentNumber" />

<br/>

리포트파일: <input type="file" name="report" />

<br/>

<input type="submit" />

</form>

위 HTML 코드에서 파일은 report 파라미터를 통해서 전달된다. 


이 경우 다음 코드와 같이 @RequestParam 어노테이션과 MultipartFile 타입의 파라미터를 이용해서 업로드 파일 데이터를 전달받을 수 있다.

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.multipart.MultipartFile;


@Controller

public class ReportSubmissionController {


@RequestMapping(value = "/report/submitReport1.do", method = RequestMethod.POST)

public String submitReport1(

@RequestParam("studentNumber") String studentNumber,

// MultipartFile이 제공하는 메서드를 이용해서 업로드 데이터 접근

@RequestParam("report") MultipartFile report) {

printInfo(studentNumber, report);

return "report/submissionComplete";

}

...

}

MultipartFile 인터페이스는 스프링에서 업로드 한 파일을 표현할 때 사용되는 인터페이스로서, MultipartFile 인터페이스를 이용해서 업로드 한 파일의 이름, 실제 데이터, 파일 크기 등을 구할 수 있다.


3. MultipartHttpServletRequest를 이용한 업로드 파일 접근


업로드한 파일을 전달받는 두 번째 방법은 MultipartHttpServletRequest 인터페이스를 이용하는 것이다.

import org.springframework.web.multipart.MultipartFile;

import org.springframework.web.multipart.MultipartHttpServletRequest;


@Controller

public class ReportSubmissionController {

@RequestMapping(value = "/report/submitReport2.do", method = RequestMethod.POST)

public String submitReport2(MultipartHttpServletRequest request) {

String studentNumber = request.getParameter("studentNumber");

MultipartFile report = request.getFile("report");

printInfo(studentNumber, report);

return "report/submissionComplete";

}

}

MultopartHttpServletRequest 인터페이스는 스프링이 제공하는 인터페이스로서, Multipart 요청이 들어올 때 내부적으로 원본 HttpServletRequest 대신 사용되는 Multipart 요청이 들어올 때 

내부적으로 원본 HttpServletRequest 대신 사용되는 인터페이스이다. MultipartHttpServletRequest 인터페이스는 실제로는 어떤 메서드도 선언하고 있지 않으며,  HttpServletRequest 인터페이스와 MultipartRequest 인터페이스를 상속받고 있다. MultipartHttpServletRequest 인터페이스는 javax.servlet.HttpServletRequest 인터페이스를 상속받기 때문에 웹 요청 정보를 구하기 위한 getParameter()나 getHeader()와 같은 메서드를 사용할 수 있으며, 추가로 MultipartRequest 인터페이스가 제공하는 Multipart 관련 메서드를 사용할 수 있다.


※ MultipartRequest 인터페이스의 파일 관련 주요 메서드

 메서드

설 명 

 Iterator<String> getFileNames()

 업로드 된 파일들의 이름 목록을 제공하는 Iterator를 구한다.

 MultipartFile getfile(String name)

 파라미터 이름이 name이 업로드 파일 정보를 구한다.

 List<MultipartFile> getFiles(String name)

 파라미터 이름이 name인 업로드 파일 정보 목록을 구한다.

 Map<String, MultipartFile> getFileMap()

 파라미터 이름을 키로 파라미터에 해당하는 파일 정보를 값으로 하는 Map을 구한다.


4. 커맨드 객체를 통한 업로드 파일 접근


커맨드 객체를 이용해도 업로드 한 파일을 전달받을 수 있다. 단지 커맨드 클래스에 파라미터와 동일한 이름의 MultipartFile 타입 프로퍼티를 추가해주기만 하면 된다.

예를 들어, 업로드 파일의 파라미터 이름이 "report"인 경우, 다음과 같이 "report" 프로퍼티를 커맨드 클래스에 추가해 주면 된다.


import org.springframework.web.multipart.MultipartFile;


public class ReportCommand {


private String studentNumber;

private MultipartFile report;


public String getStudentNumber() {

return studentNumber;

}


public void setStudentNumber(String studentNumber) {

this.studentNumber = studentNumber;

}


public MultipartFile getReport() {

return report;

}


public void setReport(MultipartFile report) {

this.report = report;

}

}


위 코드와 같이 MultipartFile 타입의 프로퍼티를 커맨드 클래스에 추가해주었다면, @RequestMapping 메서드의 커맨드 객체로 사용함으로써 업로드 파일 정보를 커맨드 객체를 통해서 전달받을 수 있게 된다.

@Controller

public class ReportSubmissionController{

...

@RequestMapping(value="/report/submitReport3.do",medhod = RequestMethod.POST)

public String submitReport3(ReportCommand reportCommand){

...

}

}


5. MultupartFile 인터페이스 사용


org.springframework.web.MutipartFile 인터페이스는 업로드 한 파일 및 파일 데이터를 표현하기 위한 용도로 사용된다.

MultipartFile 인터페이스가 제공하는 주요 메서드는 다음과 같다.


※ MulripartFile 인터페이스의 주요 메서드

 메서드

 설 명

 String getName()

 파라미터 이름을 구한다.

 String getOriginalFilename()

 업로드 한 파일의 이름을 구한다.

 String isEmpty()

 업로드 한 파일이 존재하지 않는 경우 true를 리턴한다.

 long getSize()

 업로드 한 파일의 크기를 구한다.

 byte[ ] getBytes() throws IOExcetion

 업로드 한 파일 데이터를 구한다.

 InputStream getInputStream() throws  IOException

 업로드한 파일 데이터를 읽어노는 InputStream을 구한다. InputStream의 사용  이 끝나면 알맞게 종료해  주어야 한다.

 void transferTo(File dest) throws IOException

 업로드 한 파일 데이터를 지정한 파일에 저장한다.


업로드 한 파일 데이터를 구하는 가장 단순한 방법은 MultipartFile.getByte() 메서드를 이용하는 것이다. 바이트 배열을 구한 뒤에 파일이나 DB등에 저장하면된다.

if(mutipartFile.isEmpty()){

byte[ ] fileData = multipartFile.getBytes();

//byte 배열을 파일/DB/네트워크 등으로 전송

...

}


업로드 한 파일 데이터를 특정 파일로 저장하고 싶다면 MultipartFile.transferTo() 메서드를 사용하는 것이 편리하다.

if(mutipartFile.isEmpty()){

File file = new File(fileName);

multipartFile.transferTo(file);

...

}