File Upload with Spring MVC

1. Overview

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

In this article, 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 Commons FileUpload and another 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. Commons FileUpload

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

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

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

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

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

3. With Servlet 3.0

In order to use Servlet 3.0 multipart parsing, we need to configure a couple pieces of the application. First, we need to set a MultipartConfigElement in our DispatcherServlet registration:

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.

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

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

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

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

5. Uploading Multiple Files

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:

@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

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:

@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’s a lot of additional fields along with the file. Let’ 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

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, as 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>
    <version>2.1.8.RELEASE</version>
</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.

8. Conclusion

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.

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

Related posts:

Spring Boot with Multiple SQL Import Files
Java Program to Implement Miller Rabin Primality Test Algorithm
Tạo ứng dụng Java RESTful Client không sử dụng 3rd party libraries
Reversing a Linked List in Java
Vấn đề Nhà sản xuất (Producer) – Người tiêu dùng (Consumer) và đồng bộ hóa các luồng trong Java
Setting a Request Timeout for a Spring REST API
Spring Boot - Hystrix
New Features in Java 10
Java Program to Find MST (Minimum Spanning Tree) using Kruskal’s Algorithm
Java Program to Give an Implementation of the Traditional Chinese Postman Problem
Jackson Exceptions – Problems and Solutions
Command-Line Arguments in Java
Java – Delete a File
Spring 5 and Servlet 4 – The PushBuilder
Java Program to Describe the Representation of Graph using Incidence List
Java Program to Implement Binary Heap
Concatenating Strings In Java
Java Program to Implement a Binary Search Tree using Linked Lists
Introduction to Spring Cloud Rest Client with Netflix Ribbon
Convert Hex to ASCII in Java
Properties with Spring and Spring Boot
Spring MVC Tutorial
Java Collections Interview Questions
The Dining Philosophers Problem in Java
Filtering and Transforming Collections in Guava
So sánh ArrayList và Vector trong Java
Java Program to Check Whether a Weak Link i.e. Articulation Vertex Exists in a Graph
Simplify the DAO with Spring and Java Generics
Check if a String is a Palindrome in Java
How to Get All Dates Between Two Dates?
Java Program to Implement LinkedBlockingDeque API
Remove the First Element from a List