본문 바로가기
Dev/Spring

스프링 Multipart : 파일 업로드 처리

by vellahw 2022. 10. 18.

 

 

쇼핑몰 등의 웹 사이트 구축 중 파일 업로드가 필요한 경우 HTML 폼의 속성을 multipart/form-data로 설정해야 한다.

1
2
3
<form method="post" enctype="multipart/form-data">
           ...
</form>
cs

 

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

스프링은 Multipart 지원 기능을 제공하고 있기 때문에 이 기능을 이용하면 추가적인 처리 없이 Multipart 지원 기능을 이용해서 업로드 한 파일을 처리할 수 있다.

 

 

🎈. MultipartResolver 설정

Multipart 지원 기능을 사용하려면 먼저 MultipartResolver를 스프링 설정 파일에 등록해 주어야 한다.

MultipartResolver는  Multipart 형식으로 데이터가 전송된 경우, 해당 데이터를 스프링 MVC에서 사용할 수 있도록 변환해준다. 예를 들어 @PathVariable 어노테이션을 이용해서 Multipart로 전송된 파라미터와 파일을 사용할 수 있도록 해준다.

 

스프링이 기본으로 제공하는 MultipartResolver는 CommonsMultipartResolver이다.

CommonsMultipartResolver는 CommonsFileUpload API를 이용해서 Multipart를 처리해 준다. CommonsMultipartResolver를 MultipartResolver로 사용하려면 다음과 같이 bean 이름으로 "multipartResolver"를 사용해서 등록하면 된다.

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

 

CommonsMultipartResolver 클래스는 업로드와 관련해서 아래와 같은 프로퍼티를 제공하고 있다.

프로퍼티 타입 설명
maxUploadSize long 최대 업로드 가능한 바이트 크기
-1은 제한 없음을 의미하며 기본값은 -1
maxInMemorySize int 디스크에 임시 파일을 생성하기 전에
메모리에 보관할 수 있는 최대 바이트 크기
기본값은 10240 바이트
defaultEncoding String 요청을 파싱할 때 사용할 캐릭터 인코딩
지정하지 않을 경우 HttpServletRequest.setCharacterEncoding() 메서드로 지정한 캐릭터 셋이 사용 되며,
아무 값도 없을 경우 ISO-8859-1을 사용

 

 

업로드한 파일을 전달 받는 방법에는 세 가지 방법이 있다.

  1. @RequestParam Annotation을 이용한 업로드 파일 접근
  2. MultipartHttpServletRequest를 이용한 업로드 파일 접근
  3. 커맨드 객체(자바빈)를 통한 업로드 파일 접근

 

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

@RequestParam Annotation이 적용된 MultipartFile 타입의 파라미터를 사용하여 업로드한 파일을 전달받을 수 있다.
예를 들어, HTML 입력폼이 다음과 같이 작성되어 있다고 해보자.

1
2
3
4
5
6
7
<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>
cs

 

위 HTML 코드에서 파일은 report 파라미터를 통해서 전달된다. 이 경우 다음 코드와 같이 RequestParam Annotation과 MultipartFile 타입의 파라미터를 이용해서 업로드 파일 데이터를 전달받을 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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,
        @RequestParam("report") MultipartFile report) {
            .. // MultipartFile이 제공하는 메서드를 이용해서 업로드 데이터 접근 
            return "report/submissionComplete";
    }
        ...
}        
cs

 

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

https://tavi.tistory.com/58

 

스프링 MultipartFile 인터페이스 사용

org.springframework.web.multipart.MultipartFile 인터페이스는 업로드 한 파일 정보 및 파일 데이터를 표현하기 위한 용도로 사용된다. MultipartFile Interface가 제공하는 주요 메서드는 다음과 같다. 메서..

tavi.tistory.com

 

 

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

MultipartHttpServletRequest 인터페이스를 사용하여 업로드한 파일을 전달 받을 수 있다.

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

MultipartHttpServletRequest 인터페이스는 실제로는 어떤 메서드도 선언하고 있지 않으며, HttpServletRequest 인터페이스와 MultipartRequest 인터페이스를 상속받고 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
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");
            ...
    }
}
cs

 

@RequestParam 어노테이션이 적용된 MultipartFile 타입의 파라미터를 사용하면 @RequestParam 어노테이션을 중복으로 작성 해야 하는데 MultipartHttpServletRequest 인터페이스를 사용하면 중복으로 작성하지 않아도 된다는 편리함이 있다.

MultipartHttpServletRequest 인터페이스는 javax.servlet.http.HttpServletRequest 인터페이스를 상속받기 때문에 WEB 요청 정보를 구하기 위한 getParameter()나 getHeader()와 같은 메서드를 사용할 수 있으며, 추가로 MultipartRequest 인터페이스가 제공하는 Multipart 관련 메서드를 사용할 수 있다.

MultipartRequest 인터페이스가 제공하는 업로드 파일 관련 주요 메소드
메소드 설명
Iterator<String> getFileNames() 업로드 된 파일들의 이름 목록을 제공하는 Iterator를 구한다.
MultipartFile getFile(String name) 파라미터 이름이 name인 업로드 파일 정보를 구한다.
List<MultipartFile> getFiles(String name) 파라미터 이름이 name인 업로드 파일 정보 목록을 구한다.
Map<String, MultipartFile> getFileMap() 파라미터 이름을 key로, 파라미터에 해당하는 파일 정보를 값으로 하는 Map을 구한다.

 

 

 

💡 3. 커맨드 객체(자바빈)를 통한 접근

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package spring.controller;
 
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;
    }            
}
cs

 

 

 

🎇. 파일 업로드 처리 예제

1) 자바빈 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package springMVC.controller;
 
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;
    }
}
cs

 

2) 컨트롤러 클래스 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package springMVC.controller;
 
import java.io.File;
import java.util.Date;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
 
@Controller
public class ReportSubmissionController {
    
    //업로드한 파일의 실제 저장 경로 지정
    private String uploadPath = "C:\\codingco\\eclipse-workspace\\SpringHello\\src\\main\\webapp\\files\\";
    
    @RequestMapping(value = "/report/submission.do", method = RequestMethod.GET)
    public String form() {
        return "report/submissionForm";
    }
    
    
    //출력 내용 메소드 정의 
    private void printInfo(String studentNumber, MultipartFile report) {
        System.out.println(studentNumber + "가 업로드한 파일: "
                            + report.getOriginalFilename());
    }
        
    
    //1. @RequestParam 어노테이션을 이용한 업로드 처리
    @RequestMapping(value = "/report/submitReport1.do", method = RequestMethod.POST)
    public String submitReport1(@RequestParam("studentNumber"String studentNumber,
                                @RequestParam("report") MultipartFile report) {
        
        printInfo(studentNumber, report);
        
        String fileName = report.getOriginalFilename(); //업로드한 파일의 이름 구함
        File uploadFile = new File(uploadPath + fileName); 
        
        if(uploadFile.exists()) { //업로드한 파일이 존재한다면(=똑같은 파일을 업로드 한다면)
            fileName = new Date().getTime() + fileName; //중복 파일의 이름 지정
            uploadFile = new File(uploadPath + fileName); 
        }
        
        try {
            report.transferTo(uploadFile); //업로드 파일 데이터를 uploadFile에 저장
        } catch (Exception e) {    }
        
        return "report/submissionComplete";
    }
    
    
    
    //2. MultipartHttpServletRequest를 이용한 업로드 처리
    @RequestMapping(value = "/report/submitReport2.do", method = RequestMethod.POST)
    public String submitReport2(MultipartHttpServletRequest request) {
        
        //넘어온 request를 객체로 저장
        String studentNumber = request.getParameter("studentNumber");
        MultipartFile report =request.getFile("report") ;
        printInfo(studentNumber, report);
        
        String fileName = report.getOriginalFilename();
        File uploadFile = new File(uploadPath + fileName); 
        
        if(uploadFile.exists()) { 
            fileName = new Date().getTime() + fileName; 
            uploadFile = new File(uploadPath + fileName); 
        }
        
        try { 
            report.transferTo(uploadFile);
        } catch (Exception e) {    }
        
        return "report/submissionComplete";
    }
    
    
    //3. 자바빈 객체를 이용한 업로드 처리
    @RequestMapping(value = "/report/submitReport3.do", method = RequestMethod.POST)
    public String submitReport3(ReportCommand reportCommand) {
        
        MultipartFile report = reportCommand.getReport();
        
        String fileName = report.getOriginalFilename();
        File uploadFile = new File(uploadPath + fileName); 
        
        if(uploadFile.exists()) { 
            fileName = new Date().getTime() + fileName; 
            uploadFile = new File(uploadPath + fileName); 
        }
        
        try { 
            report.transferTo(uploadFile);
        } catch (Exception e) {    }
        
        printInfo(reportCommand.getStudentNumber(), reportCommand.getReport());
        return "report/submissionComplete";
    }
}
cs

 

3) dispatcher-servlet.xml 설정 파일에 MultipartResolver 사용을 위한 bean 추가

1
2
3
4
<bean id="multipartResolver" 
            class="org.springframework.web.multipart.commons.CommonsMultipartResolver" >
</bean>
<bean class="springMVC.controller.ReportSubmissionController" />
cs

 

4) 뷰 JSP 작성

▼ submissionForm.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<%@ page language="java" contentType="text/html; charset=EUC-KR" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr" >
<title>리포트 제출</title>
</head>
<body>
<h3>@RequestParam 사용</h3>
<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>
 
<h3>MultipartHttpServletRequest 사용</h3>
<form action="submitReport2.do" method="post" enctype="multipart/form-data">
    학번: <input type="text" name="studentNumber" />
    <br/>
    리포트 파일: <input type="file" name="report" />
    <br/>
    <input type="submit" />
</form>
 
<h3>커맨드 객체 사용</h3>
<form action="submitReport3.do" method="post" enctype="multipart/form-data">
    학번: <input type="text" name="studentNumber" />
    <br/>
    리포트 파일: <input type="file" name="report" />
    <br/>
    <input type="submit" />
</form>
</body>
</html>
cs

submissionComplete.jsp

1
2
3
4
5
6
7
8
9
10
11
12
<%@ page language="java" contentType="text/html; charset=EUC-KR" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>리포트 제출 완료</title>
</head>
<body>
리포트 제출 완료
</body>
</html>
cs

 

✨실행 결과

  • 컨트롤러에서 작성한 @RequestMapping에 의해 /report/submission.do로 실행 했을 시 jsp 뷰 파일이 화면에 출력됨

 

  • '쿼리전송' 버튼을 누른 후 알맞게 실행 되는 결과

 

  • 컨트롤러에서 작성한 코드 대로 콘솔창에 출력 됨 

 

컨트롤러에서 작성한 코드대로 똑같은 파일을 업로드 했다면 파일명을 바꿔줬고

webapp/files 폴더에 파일들이 알맞게 업로드 됨

 

 

'Dev > Spring' 카테고리의 다른 글

HandlerInterceptor : 요청 가로채기  (0) 2022.10.19
@InitBinder 어노테이션  (1) 2022.10.18
스프링 MultipartFile 인터페이스 사용  (0) 2022.10.18
스프링 캐릭터 인코딩 처리 필터 설정  (0) 2022.10.17
스프링 MVC  (0) 2022.10.17

댓글