File Upload with Spring MVC – 用Spring MVC上传文件

最后修改: 2016年 4月 7日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In previous tutorials, we introduced the basics of form handling and explored the form tag library in Spring MVC.

在之前的教程中,我们介绍了表单处理的基础知识,并探索了Spring MVC中的表单标签库

In this tutorial, we focus on what Spring offers for multipart (file upload) support in web applications.

在本教程中,我们将重点讨论Spring在Web应用程序中提供的多部分(文件上传)支持

Spring allows us to enable this multipart support with pluggable MultipartResolver objects. The framework provides one MultipartResolver implementation for use with Commons FileUpload and another for use with Servlet 3.0 multipart request parsing.

Spring允许我们通过可插拔的MultipartResolver对象来实现这种多部分支持。该框架提供了一个MultipartResolver实现,用于Commons FileUpload,另一个用于Servlet 3.0多部分请求解析。

After configuring the MultipartResolver, we’ll see how to upload a single file and multiple files.

在配置了MultipartResolver之后,我们将看到如何上传单个文件和多个文件。

We’ll also touch on Spring Boot.

我们还将讨论Spring Boot.

2. Commons FileUpload

2.Commons FileUpload

To use CommonsMultipartResolver to handle the file upload, we need to add the following dependency:

为了使用CommonsMultipartResolver来处理文件上传,我们需要添加以下依赖。

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

Now we can define the CommonsMultipartResolver bean in our Spring configuration.

现在我们可以在Spring配置中定义CommonsMultipartResolver Bean。

This MultipartResolver comes with a series of set methods to define properties such as the maximum size for uploads:

这个MultipartResolver带有一系列set方法,用于定义属性,如上传的最大尺寸。

@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setMaxUploadSize(100000);
    return multipartResolver;
}

Here we need to control different properties of CommonsMultipartResolver in the Bean definition itself.

这里我们需要在Bean定义本身中控制CommonsMultipartResolver的不同属性。

3. With Servlet 3.0

3.有了Servlet 3.0之后

In order to use Servlet 3.0 multipart parsing, we need to configure a couple pieces of the application.

为了使用Servlet 3.0多部分解析,我们需要配置应用程序的几个部分。

First, we need to set a MultipartConfigElement in our DispatcherServletregistration:

首先,我们需要在我们的DispatcherServletregistration中设置一个MultipartConfigElement

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);
    }
}

In the MultipartConfigElement object, we have configured the storage location, maximum individual file size, maximum request size (in the case of multiple files in a single request), and the size at which the file upload progress is flushed to the storage location.

MultipartConfigElement对象中,我们已经配置了存储位置、最大的单个文件大小、最大的请求大小(在单个请求中有多个文件的情况下),以及文件上传进度被刷新到存储位置的大小。

These settings must be applied at the servlet registration level because Servlet 3.0 does not allow them to be registered in the MultipartResolver as is the case with CommonsMultipartResolver.

这些设置必须在Servlet注册级别上应用,因为Servlet 3.0不允许它们在MultipartResolver中注册,就像CommonsMultipartResolver那样。

Once this is done, we can add the StandardServletMultipartResolver to our Spring configuration:

一旦完成,我们可以将StandardServletMultipartResolver添加到我们的Spring配置中

@Bean
public StandardServletMultipartResolver multipartResolver() {
    return new StandardServletMultipartResolver();
}

4. Uploading a File

4.上传文件

To upload our file, we can build a simple form in which we use an HTML input tag with type=’file’.

为了上传我们的文件,我们可以建立一个简单的表单,在其中使用一个HTML input标签,type=’file’

Regardless of the upload handling configuration we have chosen, we need to set the encoding attribute of the form to multipart/form-data.

无论我们选择哪种上传处理配置,我们都需要将表单的编码属性设置为multipart/form-data

This lets the browser know how to encode the form:

这让浏览器知道如何对表格进行编码。

<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>

To store the uploaded file, we can use a MultipartFile variable.

为了存储上传的文件,我们可以使用一个MultipartFile变量。

We can retrieve this variable from the request parameter inside our controller’s method:

我们可以在控制器的方法中从请求参数中检索这个变量。

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

The MultipartFile class provides access to details about the uploaded file, including file name, file type and so on.

MultipartFile类提供了对上传文件细节的访问,包括文件名、文件类型等等。

We can use a simple HTML page to display this information:

我们可以使用一个简单的HTML页面来显示这些信息。

<h2>Submitted File</h2>
<table>
    <tr>
        <td>OriginalFileName:</td>
        <td>${file.originalFilename}</td>
    </tr>
    <tr>
        <td>Type:</td>
        <td>${file.contentType}</td>
    </tr>
</table>

5. Uploading Multiple Files

5.上传多个文件

To upload multiple files in a single request, we simply put multiple input file fields inside the form:

为了在一个请求中上传多个文件,我们只需在表单中放入多个输入文件字段。

<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>

We need to take care that each input field has the same name so that it can be accessed as an array of MultipartFile:

我们需要注意每个输入字段都有相同的名称,以便它可以作为MultipartFile的数组被访问。

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

Now we can simply iterate over that array to display files information:

现在我们可以简单地迭代该数组来显示文件信息。

<%@ 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>

6. Uploading Files With Additional Form Data

6.用附加表格数据上传文件

We can also send additional information to the server along with the file being uploaded.

我们还可以在上传文件的同时向服务器发送额外信息。

We just have to include the required fields in the form:

我们只需在表格中加入必要的字段。

<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>

In the controller, we can get all the form data using the @RequestParam annotation:

在控制器中,我们可以使用@RequestParam注解获得所有表单数据。

@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";
}

Similar to previous sections, we can use the HTML page with JSTL tags to display the information.

与前几节类似,我们可以使用带有JSTL标签的HTML页面来显示信息。

We can also encapsulate all the form fields in a model class and use @ModelAttribute annotation in the controller. This would be helpful when there’s a lot of additional fields along with the file.

我们也可以将所有的表单字段封装在一个模型类中,并在控制器中使用@ModelAttribute注解。当有很多额外的字段与文件一起出现时,这将会很有帮助。

Let’s look at the code:

让我们看一下代码。

public class FormDataWithFile {

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

    // standard getters and setters
}
@PostMapping("/uploadFileModelAttribute")
public String submit(@ModelAttribute FormDataWithFile formDataWithFile, ModelMap modelMap) {

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

7. Spring Boot File Upload

7.Spring Boot文件上传

If we’re using Spring Boot, everything we’ve seen so far still applies.

如果我们使用Spring Boot,到目前为止我们看到的一切仍然适用。

However, Spring Boot makes it even easier to configure and start everything with little hassle.

然而,Spring Boot使配置和启动一切变得更加容易,没有什么麻烦。

In particular, it’s not necessary to configure any servlet since Boot will register and configure it for us, provided that we include the web module in our dependencies:

特别是,不需要配置任何servlet,因为Boot将为我们注册和配置它,只要我们在依赖关系中包括web模块。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.7.2</version>
</dependency>

We can find the latest version of spring-boot-starter-web on Maven Central.

我们可以在Maven中心找到最新版本的spring-boot-starter-web

If we want to control the maximum file upload size, we can edit our application.properties:

如果我们想控制最大文件上传尺寸,我们可以编辑我们的application.properties

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

We can also control whether file uploading is enabled and the location for file upload:

我们还可以控制是否启用文件上传以及文件上传的位置。

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

Note that we’ve used ${java.io.tmpdir} to define the upload location so that we can use the temporary location for different operating systems.

注意,我们使用了${java.io.tmpdir}来定义上传位置,这样我们就可以在不同的操作系统中使用临时位置。

8. Conclusion

8.结论

In this article, we looked at different ways to configure multipart support in Spring. Using these, we can support file uploads in our web applications.

在本文中,我们研究了在Spring中配置多部分支持的不同方法。使用这些方法,我们可以在我们的Web应用程序中支持文件上传。

The implementation of this tutorial can be found in the GitHub project. When the project runs locally, the form example can be accessed at http://localhost:8080/spring-mvc-java/fileUpload

本教程的实现可以在GitHub项目中找到。当该项目在本地运行时,可以通过以下网址访问表单示例:http://localhost:8080/spring-mvc-java/fileUpload