Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

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

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

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

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

We’ll also touch on Spring Boot.

2. Configurations With Servlet 3.0

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

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

public class MainWebAppInitializer implements WebApplicationInitializer {

    private static final String TMP_FOLDER = "/tmp"; 
    private static final 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 * 2L, 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.

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

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

3. Uploading a File

To upload our file, we can build a simple form in which we use an HTML input tag with 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.

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.

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.

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

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

When the project runs locally, the form example can be accessed at http://localhost:8080/spring-mvc-java/fileUpload.

4. Uploading Multiple Files

To upload multiple files in a single request, we 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:

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

Now, we can iterate over that array to display file 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>

5. Uploading Files With Additional Form Data

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

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

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

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 are a lot of additional fields along with the file.

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

6. Spring Boot File Upload

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

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

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:

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

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

If we want to control the maximum file upload size, we can edit our 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.

7. Conclusion

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

The implementation of this tutorial can be found in the GitHub project.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.