MultipartFile을 사용한 File 업로드

(multipart/form-data)

 

 

SpringFramework환경의 서버라면 SpringFramework에서 제공하고 있는 MultipartFile 클래스와 MultipartHttpServletRequest 클래스를 사용해서 File 업로드 기능을 구현할 수 있습니다. 이 두가지 클래스를 사용해서 어떻게 File 업로드 기능이 구현될 수 있는지 Controller로 들어오는 요청 파라미터의 타입을 기준으로 3가지 방법으로 나눠서 살펴보겠습니다. 참고로, 이 포스팅에서 소개하는 FIle 업로드 방식으로 클라이언트에서 서버로 HTTP 요청을 할 때, “Content-Type” 필드의 내용을 “multipart/form-data”로 세팅해서 요청해야 합니다.

 

 

1번째 방법@RequestParam MultipartFile 타입 사용
2번째 방법ServletRequest or MultipartHttpServletRequest 타입 사용
3번째 방법사용자 정의 Class 타입 사용 

 

 

[ Controller에서 multipart/form-data 타입의 메시지를 받는 3가지 방법 ]

 

 

 

1. @RequetParam MultipartFile 타입을 사용하는 방법

[ @RequestParam MultipartFile 사용 ]


요청파라미터 타입을 @RequestParam 어노테이션과 함께 사용하는 경우입니다. 이 경우, 서버는 클라이언트의 HTTP 요청 메시지에 포함된 파라미터들을 모두 분리해서 컨트롤할 수 있기 때문에, 컨트롤러의 요청파라미터 타입 중 MultipartFile타입에 해당하는 한가지를 직접 골라서, file 데이터를 직접 다룰 수 있다는 장점이 있지만, file 데이터 외에 다른 파라미터들(ex, String, Integer, MultipartFile)을 몇가지 추가해서 함께 받는다면 코드가 조금 지저분해질 수도 있다는 단점이 있습니다.

 

코드 : MultipartController.java

@RestController
public class MultipartController {
	@RequestMapping(value = {"/upload"}, method = {RequestMethod.POST}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
	public String upload(@RequestParam("file") MultipartFile file) throws IOException {

		System.out.println(file.getName()); // 파일의 파라미터 이름
		System.out.println(file.getSize()); // 파일의 사이즈
		System.out.println(file.getOriginalFilename()); // 파일의 실제 이름
		byte[] data = file.getBytes(); // 파일실제  내용
		
		return "success";
	}
}

 

 

 

 

2. MultipartServletRequest or HttpServletRequest 타입을 사용하는 방법  

[ HttpServletRequest, MultipartServletRequest 사용 ]


요청파라미터 타입을 HttpServletRequest 혹은 MultipartServletRequest 타입으로 사용하는 경우입니다. 이 경우, 서버는 클라이언트의 HTTP 요청 메시지 자체를 컨트롤 하는 것이기 때문에, 함수 내에서 요청 메시지 안에 포함된 파라미터들을 뜯어내야하는 코드를 작성해야 합니다. 이 경우, 요청 메시지안에 포함된 파라미터가 한 두개라면 괜찮겠지만, 한 두개가 아니고 많이 뜯어내야 하는 경우라면 조금 더러워질 수 있습니다. HttServletRequest 객체안에 포함된 요청 파라미터들 중에서 File 데이터를 추출할 때는 MultipartHttpServletRequest와 MultipartFile을 사용해서 추출할 수 있습니다.

 

코드 : MultipartController.java

HttpServletRequest 타입을 사용하는 경우

@RestController
public class MultipartController {
	@RequestMapping(value = {"/upload2"}, method = {RequestMethod.POST}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
	public String upload2(HttpServletRequest request) throws IOException {
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		MultipartFile file = multipartRequest.getFile("file");
		
		System.out.println(file.getName()); // 파일의 파라미터 이름
		System.out.println(file.getSize()); // 파일의 사이즈
		System.out.println(file.getOriginalFilename()); // 파일의 실제 이름
		byte[] data = file.getBytes(); // 파일실제  내용
		
		return "success-upload2";
	}
}

 

MultipartHttpServletRequest 타입을 사용하는 경우

@RestController
public class MultipartController {
	@RequestMapping(value = {"/upload3"}, method = {RequestMethod.POST}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
	public String upload3(MultipartHttpServletRequest request) throws IOException {
		MultipartFile file = request.getFile("file");
		
		System.out.println(file.getName()); // 파일의 파라미터 이름
		System.out.println(file.getSize()); // 파일의 사이즈
		System.out.println(file.getOriginalFilename()); // 파일의 실제 이름
		byte[] data = file.getBytes(); // 파일실제  내용
		
		return "success-upload3";
	}
}

 

 

 

3. 사용자 정의 Class 타입을 사용하는 방법 

[ 사용자 정의 Class 사용 ]


요청파라미터 타입을 사용자가 정의한 클래스 타입으로 사용하는 경우입니다. 참고로, 여기서 요청 파라미터로 사용되는 사용자가 정의한 클래스 타입을 SpringFramework에서는 커맨드 객체(Command Object)라고 부르고 있습니다. 이 경우, 서버는 클라이언트의 HTTP 요청 메시지에 포함된 파라미터들이 모두 자동으로 사용자가 정의한 클래스의 구조에 맞게 파싱되기 때문에, 결과적으로 개발자는 하나의 Command Object로 컨트롤할 수 있습니다. 이 방법은 클라이언트가 보내는 파라미터들이 담겨있는 클래스를 사용자가 미리 만들어놓아야 하는 귀찮음이 있지만, 요청파라미터를 여러 개 받는 것보다는 코드가 훨씬 깔끔해질 수 있다는 장점이 있기 때문에 개인적으로 왠만하면 이 방법을 선호합니다. 이 방법을 사용해서 파일 업로드를 구현한다면, 개발자는 해당 클래스를 정의할 때 File을 받을 수 있는 MultipartFile타입에 대한 변수를 클래스 내에 함께 작성해두면 됩니다.

 

코드 : MultipartController.java

@RestController
public class MultipartController {
	@RequestMapping(value = {"/upload4"}, method = {RequestMethod.POST}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
	public String upload4(MyCommand cmd) throws IOException {
		MultipartFile file = cmd.getFile();
		
		System.out.println(file.getName()); // 파일의 파라미터 이름
		System.out.println(file.getSize()); // 파일의 사이즈
		System.out.println(file.getOriginalFilename()); // 파일의 실제 이름
		byte[] data = file.getBytes(); // 파일실제  내용
		
		return "success-upload4";
	}
}

 

코드 : MyCommand.java

public class MyCommand {
	MultipartFile file;

	public MultipartFile getFile() {
		return file;
	}
	public void setFile(MultipartFile file) {
		this.file = file;
	}
}

 

 

참고

MultipartFile
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/multipart/MultipartFile.html
MultipartHttpServletRequest
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/multipart/MultipartHttpServletRequest.html