Post

Spring 파일 업로드

1. 커먼즈 파일 업로드

CommonsMultipartResolver를 사용하여 파일 업로드를 처리하려면 다음 종속성을 추가해야 한다.

1
2
3
4
5
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

이제 Spring 구성에서 CommonsMultipartResolver 빈을 정의할 수 있다.

이 MultipartResolver는 업로드를 위한 최대 크기와 같은 속성을 정의하는 일련의 set 메서드와 함께 제공된다.

1
2
3
4
5
6
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setMaxUploadSize(100000);
    return multipartResolver;
}

여기서 Bean 정의 자체에서 CommonsMultipartResolver의 다른 속성을 제어해야 한다.

2. 서블릿 3.0

Servlet 3.0 멀티파트 구문 분석을 사용하려면 몇 가지 응용 프로그램을 구성해야 한다.

먼저 DispatcherServlet 등록에서 MultipartConfigElement를 설정해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MainWebAppInitializer implements WebApplicationInitializer {

    private String TMP_FOLDER = "/tmp"; 
    private int MAX_UPLOAD_SIZE = 5 * 1024 * 1024; 
    
    @Override
    public void onStartup(ServletContext sc) throws ServletException {
        
        ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext()));
        appServlet.setLoadOnStartup(1);
        
        MultipartConfigElement multipartConfigElement = new MultipartConfigElement(TMP_FOLDER, MAX_UPLOAD_SIZE, MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2);
        appServlet.setMultipartConfig(multipartConfigElement);
    }
}

MultipartConfigElement 개체에서 저장 위치, 최대 개별 파일 크기, 최대 요청 크기(단일 요청에 여러 파일이 있는 경우) 및 파일 업로드 진행률이 저장 위치로 플러시되는 크기를 구성했다.

이러한 설정은 CommonsMultipartResolver의 경우와 같이 Servlet 3.0에서 MultipartResolver에 등록되는 것을 허용하지 않기 때문에 서블릿 등록 수준에서 적용되어야 한다.

이 작업이 완료되면 Spring 구성에 StandardServletMultipartResolver를 추가할 수 있다.

1
2
3
4
@Bean
public StandardServletMultipartResolver multipartResolver() {
    return new StandardServletMultipartResolver();
}

3. 파일 업로드

파일을 업로드하기 위해 type='file' 과 함께 HTML 입력 태그를 사용하는 간단한 양식을 작성할 수 있다.

선택한 업로드 처리 구성에 관계없이 양식의 인코딩 속성을 multipart/form-data로 설정해야 한다.

이렇게 하면 브라우저가 양식을 인코딩하는 방법을 알 수 있다.

1
2
3
4
5
6
7
8
9
10
11
<form:form method="POST" action="/spring-mvc-xml/uploadFile" enctype="multipart/form-data">
    <table>
        <tr>
            <td><form:label path="file">Select a file to upload</form:label></td>
            <td><input type="file" name="file" /></td>
        </tr>
        <tr>
            <td><input type="submit" value="Submit" /></td>
        </tr>
    </table>
</form>

업로드된 파일을 저장하기 위해 MultipartFile 변수를 사용할 수 있다.

컨트롤러 메서드 내부의 요청 매개변수에서 이 변수를 검색할 수 있다.

1
2
3
4
5
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public String submit(@RequestParam("file") MultipartFile file, ModelMap modelMap) {
    modelMap.addAttribute("file", file);
    return "fileUploadView";
}

MultipartFile 클래스는 파일 이름, 파일 유형 등을 포함하여 업로드된 파일에 대한 세부 정보에 대한 액세스를 제공한다.

간단한 HTML 페이지를 사용하여 이 정보를 표시할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
<h2>Submitted File</h2>
<table>
    <tr>
        <td>OriginalFileName:</td>
        <td>${file.originalFilename}</td>
    </tr>
    <tr>
        <td>Type:</td>
        <td>${file.contentType}</td>
    </tr>
</table>

4. 여러 파일 업로드

단일 요청으로 여러 파일을 업로드하려면 양식에 여러 입력 파일 필드를 넣기만 하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<form:form method="POST" action="/spring-mvc-java/uploadMultiFile" enctype="multipart/form-data">
    <table>
        <tr>
            <td>Select a file to upload</td>
            <td><input type="file" name="files" /></td>
        </tr>
        <tr>
            <td>Select a file to upload</td>
            <td><input type="file" name="files" /></td>
        </tr>
        <tr>
            <td>Select a file to upload</td>
            <td><input type="file" name="files" /></td>
        </tr>
        <tr>
            <td><input type="submit" value="Submit" /></td>
        </tr>
    </table>
</form:form>

MultipartFile의 배열로 액세스할 수 있도록 각 입력 필드가 동일한 이름을 갖도록 주의해야 한다.

1
2
3
4
5
@RequestMapping(value = "/uploadMultiFile", method = RequestMethod.POST)
public String submit(@RequestParam("files") MultipartFile[] files, ModelMap modelMap) {
    modelMap.addAttribute("files", files);
    return "fileUploadView";
}

이제 해당 배열을 반복하여 파일 정보를 표시할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
    <head>
        <title>Spring MVC File Upload</title>
    </head>
    <body>
        <h2>Submitted Files</h2>
        <table>
            <c:forEach items="${files}" var="file">
                <tr>
                    <td>OriginalFileName:</td>
                    <td>${file.originalFilename}</td>
                </tr>
                <tr>
                    <td>Type:</td>
                    <td>${file.contentType}</td>
                </tr>
            </c:forEach>
        </table>
    </body>
</html>

5. 추가 양식 데이터가 있는 파일 업로드

업로드 중인 파일과 함께 서버에 추가 정보를 보낼 수도 있다.

양식에 필수 필드를 포함하기만 하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<form:form method="POST" action="/spring-mvc-java/uploadFileWithAddtionalData" enctype="multipart/form-data">
    <table>
        <tr>
            <td>Name</td>
            <td><input type="text" name="name" /></td>
        </tr>
        <tr>
            <td>Email</td>
            <td><input type="text" name="email" /></td>
        </tr>
        <tr>
            <td>Select a file to upload</td>
            <td><input type="file" name="file" /></td>
        </tr>
        <tr>
            <td><input type="submit" value="Submit" /></td>
        </tr>
    </table>
</form:form>

컨트롤러에서 @RequestParam 주석을 사용하여 모든 양식 데이터를 가져올 수 있다.

1
2
3
4
5
6
7
8
9
10
@PostMapping("/uploadFileWithAddtionalData")
public String submit(
  @RequestParam MultipartFile file, @RequestParam String name,
  @RequestParam String email, ModelMap modelMap) {

    modelMap.addAttribute("name", name);
    modelMap.addAttribute("email", email);
    modelMap.addAttribute("file", file);
    return "fileUploadView";
}

JSTL 태그가 있는 HTML 페이지를 사용하여 정보를 표시할 수 있다.

또한 모델 클래스의 모든 양식 필드를 캡슐화하고 컨트롤러에서 @ModelAttribute 주석을 사용할 수 있다. 이것은 파일과 함께 많은 추가 필드가 있을 때 유용하다.

1
2
3
4
5
6
7
8
public class FormDataWithFile {

    private String name;
    private String email;
    private MultipartFile file;

    // standard getters and setters
}
1
2
3
4
5
6
@PostMapping("/uploadFileModelAttribute")
public String submit(@ModelAttribute FormDataWithFile formDataWithFile, ModelMap modelMap) {

    modelMap.addAttribute("formDataWithFile", formDataWithFile);
    return "fileUploadView";
}

6. 스프링 부트 파일 업로드

Spring Boot를 사용하고 있다면 지금까지 본 모든 것이 여전히 적용된다.

그러나 Spring Boot를 사용하면 번거로움 없이 모든 것을 훨씬 더 쉽게 구성하고 시작할 수 있다.

특히 의존성에 웹 모듈을 포함한다면 부트가 서블릿을 등록하고 구성할 것이기 때문에 어떤 서블릿도 구성할 필요가 없다.

1
2
3
4
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

최대 파일 업로드 크기를 제어하려면 application.properties를 편집할 수 있다.

spring.servlet.multipart.max-file-size=128KB
spring.servlet.multipart.max-request-size=128KB

또한 파일 업로드 활성화 여부와 파일 업로드 위치를 제어할 수 있다.

spring.servlet.multipart.enabled=true
spring.servlet.multipart.location=${java.io.tmpdir}

다른 운영 체제에 임시 위치를 사용할 수 있도록 ${java.io.tmpdir}을 사용하여 업로드 위치를 정의했다.

[출처 및 참고]

This post is licensed under CC BY 4.0 by the author.