Spring MVC Multiple File Upload Example

This example will show you how to implement multiple file upload and single file upload functions in spring MVC. First, let us look at the demo video as below. There are two parts on the page, the top part can upload three files and the bottom part can upload one file. After you upload the file, you can see the uploaded files are saved in the server folder /tmp/upload_example.

If you can not watch the above video, you can see it on the youtube URL https://youtu.be/ukmPfGvlBAo

1. Create Spring MVC Project.

  1. Create a Spring MVC project for our upload file example is STS. You can refer to Spring MVC Full Java Based Configuration Example to learn how to do it.
  2. The spring MVC project name is SpringMVCFileUpload_, it is a Simple Spring Maven type spring project.
  3. After creating the project, when the example files have been added or edited successfully, you should see the project files as below. This project is a java-config annotation-based spring project, we will introduce the source files one by one.
    C:\WORKSPACE\WORK\DEV2QA.COM-EXAMPLE-CODE\SPRINGBOOT\SPRINGMVCFILEUPLOAD
    │   .classpath
    │   .project
    │   .springBeans
    │   pom.xml
    │
    ├───.settings
    │       org.eclipse.core.resources.prefs
    │       org.eclipse.jdt.core.prefs
    │       org.eclipse.m2e.core.prefs
    │
    ├───src
    │   └───main
    │       ├───java
    │       │   └───com
    │       │       └───dev2qa
    │       │           └───mvc
    │       │               └───fileupload
    │       │                   ├───config
    │       │                   │       SpringConfig.java
    │       │                   │       SpringDispatcherServlet.java
    │       │                   │
    │       │                   ├───controller
    │       │                   │       UploadFileController.java
    │       │                   │
    │       │                   └───model
    │       │                           FileUploadFormData.java
    │       │
    │       ├───resources
    │       │   └───config
    │       │           messages_en_US.properties
    │       │           views.properties
    │       │
    │       └───webapp
    │           └───pages
    │                   upload_file_main.jsp
    │                   upload_file_result.jsp
    │                   upload_file_show_form.jsp

 

2. Spring Config Java File.

  1. This class is used to configure project used spring beans.
  2. The class’s getMultipartFormResolver() method just returns the CommonsMultipartResolver bean that can resolve the file upload issue automatically.
  3. SpringConfig.java
    package com.dev2qa.mvc.fileupload.config;
    
    import java.io.IOException;
    
    import org.springframework.context.MessageSource;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.support.ReloadableResourceBundleMessageSource;
    import org.springframework.web.multipart.commons.CommonsMultipartResolver;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    import org.springframework.web.servlet.view.ResourceBundleViewResolver;
    
    @EnableWebMvc
    @Configuration
    @ComponentScan(basePackages="com.dev2qa.mvc.fileupload")
    public class SpringConfig extends WebMvcConfigurerAdapter {
    
        public static final String ENCODING_UTF_8 = "UTF-8";
    
        public static final long MAX_UPLOAD_FILE_SIZE = 52428807;
    
        public static final long MAX_UPLOAD_PER_FILE_SIZE = 5242880;
    
        /* CommonsMultipartResolver class provide function that can parse and get the upload file name, data etc. */
        @Bean(name = "multipartResolver")
        public CommonsMultipartResolver getMultipartFormResolver() throws IOException{
    
            CommonsMultipartResolver ret = new CommonsMultipartResolver();
    
            ret.setMaxUploadSize(MAX_UPLOAD_FILE_SIZE);
    
            ret.setMaxUploadSizePerFile(MAX_UPLOAD_PER_FILE_SIZE);
    
            ret.setDefaultEncoding(ENCODING_UTF_8);
    
            return ret;
        }
    
        /* ResourceBundleViewResolver is used to create the returned view object based on the configuration file src/main/resources/config/views.properties. */
        @Bean
        public ResourceBundleViewResolver getBundleViewResolver() {
    
            ResourceBundleViewResolver ret = new ResourceBundleViewResolver();
    
            ret.setBasename("config.views");
    
            ret.setOrder(0);
    
            return ret;
        }
    
        /* messageSource method name can not be change to others, else there will has errors when browse web page.
         * MessageSource can help jsp page display the messages defined in the src/main/resources/config/messages_en_US.properties file easily.
         * */
        @Bean(name = "messageSource")
        public MessageSource getMessageSource() {
            ReloadableResourceBundleMessageSource ret = new ReloadableResourceBundleMessageSource();
    
            ret.setBasename("classpath:config/messages_en_US");
    
            ret.setCacheSeconds(1);
    
            ret.setUseCodeAsDefaultMessage(true);
    
            ret.setDefaultEncoding(ENCODING_UTF_8);
    
            return ret;
        }
    }

3. Spring Dispatcher Servlet Java File.

  1. This class is used to add spring dispatcher servlet and add file upload settings to the servlet.
  2. SpringDispatcherServlet.java
    package com.dev2qa.mvc.fileupload.config;
    
    import javax.servlet.FilterRegistration;
    import javax.servlet.MultipartConfigElement;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRegistration;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.WebApplicationInitializer;
    import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
    import org.springframework.web.multipart.support.MultipartFilter;
    import org.springframework.web.servlet.DispatcherServlet;
    
    @Configuration
    public class SpringDispatcherServlet implements WebApplicationInitializer {
    
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
    
            AnnotationConfigWebApplicationContext dispatcherServletContext = new AnnotationConfigWebApplicationContext();
    
            dispatcherServletContext.register(SpringConfig.class);
    
            DispatcherServlet dispatcherServlet = new DispatcherServlet(dispatcherServletContext);
    
            ServletRegistration.Dynamic dispatcher = servletContext.addServlet("file-upload", dispatcherServlet);
             
            /* If do not set multipartconfig in servlet 3, when you upload a file, it will throw Unable to process parts as no multi-part configuration has been provided error. */
            MultipartConfigElement multipartConfig = new MultipartConfigElement("/tmp");
            dispatcher.setMultipartConfig(multipartConfig);
    
            dispatcher.setLoadOnStartup(1);
    
            dispatcher.addMapping("*.html");
    
            FilterRegistration.Dynamic multipartFilter = servletContext.addFilter("multipartFilter", MultipartFilter.class);
    
            multipartFilter.addMappingForUrlPatterns(null, true, "/*");
        }
    
    }

4. Upload File Controller Java File.

  1. This class is the spring MVC controller class that will process file upload action.
  2. It contains two methods, one is used to process multiple file uploads the other is used to process single file upload.
  3. UploadFileController.java
    package com.dev2qa.mvc.fileupload.controller;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.Iterator;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.multipart.MultipartFile;
    import org.springframework.web.multipart.MultipartHttpServletRequest;
    
    import com.dev2qa.mvc.fileupload.model.FileUploadFormData;
    
    @Controller
    @RequestMapping("/upload_file")
    public class UploadFileController {
        // This is the server side upload file save folder, make sure the folder exist before run the upload file example.
        private static final String UPLOAD_FILE_SAVE_FOLDER = "/tmp/upload_example/";
    
        /* This method will display the upload file form page. */
        @RequestMapping(value="/show_upload_file_form.html", method= {RequestMethod.GET, RequestMethod.POST})
        public String uploadFileGetForm(Model model) {
    
            FileUploadFormData fileUploadFormData = new FileUploadFormData();
    
            model.addAttribute("fileUploadFormData", fileUploadFormData);
    
            // Return the upload file form page.
            return "upload_file_show_form";
        }
    
        /* This method will display a page that contains a link and a button which will link to the upload file form page. */
        @RequestMapping(value="/main.html", method= {RequestMethod.GET, RequestMethod.POST})
        public String displayMainPage(Model model) {
    
            return "upload_file_main";
        }
    
    
        /* Process multiple file upload action and return a result page to user. */
        @RequestMapping(value="/upload_multiple_file.html", method={RequestMethod.PUT, RequestMethod.POST})
        public String uploadFileSubmit(Model model, MultipartHttpServletRequest multipartRequest) {
            try
            {
                StringBuffer msgBuf = new StringBuffer();
    
                // Get multiple file control names.
                Iterator<String> it = multipartRequest.getFileNames();
    
                while(it.hasNext())
                {
                    String fileControlName = it.next();
    
                    MultipartFile srcFile = multipartRequest.getFile(fileControlName);
    
                    String uploadFileName = srcFile.getOriginalFilename();
    
                    // Create server side target file path.
                    String destFilePath = UPLOAD_FILE_SAVE_FOLDER+uploadFileName;
    
                    File destFile = new File(destFilePath);
    
                    // Save uploaded file to target.
                    srcFile.transferTo(destFile);
    
                    msgBuf.append("Upload file " + uploadFileName + " is saved to " + destFilePath + "<br/><br/>");
                }
    
                // Set message that will be displayed in return page.
                model.addAttribute("message", msgBuf.toString());
    
            }catch(IOException ex)
            {
                ex.printStackTrace();
            }finally
            {
                return "upload_file_result";
            }
        }
    
    
        /* Process one file upload action and return a result page to user. */
        @RequestMapping(value="/upload_one_file.html", method={RequestMethod.PUT, RequestMethod.POST})
        public String uploadOneFileSubmit(Model model, @ModelAttribute("fileUploadFormData") FileUploadFormData fileUploadFormData, HttpServletRequest req) {
            try
            {
                // Get upload file.
                MultipartFile uploadFile = fileUploadFormData.getFile();
    
                // Get file name.
                String fileName = uploadFile.getOriginalFilename();
    
                // Create server side target file path.
                String destFilePath = UPLOAD_FILE_SAVE_FOLDER+fileName;
    
                File destFile = new File(destFilePath);
    
                // Save uploaded file to target.
                uploadFile.transferTo(destFile);
    
                // Set message that will be displayed in return page.
                model.addAttribute("message", "Upload file is saved to '" + destFilePath + "'");
    
            }catch(IOException ex)
            {
                ex.printStackTrace();
            }finally
            {
                return "upload_file_result";
            }
        }
    
    }

5. File Upload Model Java File.

  1. This file is just used when uploading a single file. It contains a MultipartFile property, and CommonsMultipartResolver will parse out the upload file and assign the uploaded file to the property.
  2. For multiple file uploads, you should use MultipartHttpServletRequest to resolve the upload files. You can see the example code in UploadFileController.java.
  3. FileUploadFormData.java
    package com.dev2qa.mvc.fileupload.model;
    
    import org.springframework.web.multipart.MultipartFile;
    
    public class FileUploadFormData {
    
        /* MultipartFile is used to save the uploaded file content. 
         * */
        private MultipartFile file = null;
    
        public MultipartFile getFile() {
            return file;
        }
    
        public void setFile(MultipartFile file) {
            this.file = file;
        }
    }

6. Messages Properties File.

  1. This file is saved in the src/main/resources/config folder. It defines the text messages that will be used in the JSP file.
  2. messages_en_US.properties
    #Title Labels
    upload_file_main_title=Upload File Main
    upload_file_result_title=Upload File Result
    upload_file_form_title=Upload File Form

7. ResourceBundleViewResolver Configuration Files.

  1. This file is saved in the src/main/resources/config folder. It is used to define the returned JSTL view object-related JSP pages.
  2. views.properties
    # View definition for upload file form.
    upload_file_main.(class)=org.springframework.web.servlet.view.JstlView
    upload_file_main.url=/pages/upload_file_main.jsp
    
    upload_file_show_form.(class)=org.springframework.web.servlet.view.JstlView
    upload_file_show_form.url=/pages/upload_file_show_form.jsp
    
    upload_file_result.(class)=org.springframework.web.servlet.view.JstlView
    upload_file_result.url=/pages/upload_file_result.jsp

8. File Upload Example JSP Files.

  1. All the JSP files are saved in the src/main/webapp/pages folder.
  2. There are three JSP files in this example.
  3. upload_file_main.jsp : Display the example entrance page.
  4. upload_file_show_form.jsp : Display the upload file form page.
  5. upload_file_result.jsp : Display the upload file result page.

8.1 upload_file_main.jsp

  1. This is the upload file example main JSP file, it contains one link and one submit button, all the links will direct the user to the upload file form page.
    spring-mvc-upload-files-example-main-jsp-page
  2. upload_file_main.jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
        <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title><spring:message code="upload_file_main_title" /></title>
    </head>
    <body>
        <a href="${pageContext.request.contextPath}/upload_file/show_upload_file_form.html">Go To Upload File Form Page</a>
        <br/>
        <form action="${pageContext.request.contextPath}/upload_file/show_upload_file_form.html" method="post">
            <input type="submit" value="Go To Upload File Form Page" />
        </form>
    </body>
    </html>

8.2 upload_file_show_form.jsp

  1. upload_file_show_form.jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
        <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title><spring:message code="upload_file_form_title" /></title>
    </head>
    <body>
        <b>1. Upload Multiple File Example</b>
        <form:form modelAttribute="uploadFileFormData"
            action="${pageContext.request.contextPath}/upload_file/upload_multiple_file.html"
            enctype="multipart/form-data"
            method="Post">
            <input type="file" name="fileOne" /><br/>
            <input type="file" name="fileTwo" /><br/>
            <input type="file" name="fileThree" /><br/><br/>
            <input type="submit" value="Submit"/>
        </form:form>
        <hr/>
        <b>2. Upload One File Example</b>
        <form:form modelAttribute="uploadFileFormData"
            action="${pageContext.request.contextPath}/upload_file/upload_one_file.html"
            enctype="multipart/form-data"
            method="Post">
            <input type="file" name="file" /><br/><br/>
            <input type="submit" value="Submit"/>
        </form:form>
    </body>
    </html>

8.3 upload_file_result.jsp

  1. upload_file_result.jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
        <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title><spring:message code="upload_file_result_title" /></title>
    </head>
    <body>
        ${ message }
    </body>
    </html>

9. pom.xml

  1. Our project is managed by maven, so the pom.xml file is a must-have.
  2. Copy the below code to overwrite your pom.xml content.
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.dev2qa</groupId>
        <artifactId>SpringMVCFileUpload</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>war</packaging>
        <name>Spring MVC File Upload Download</name>
    
        <properties>
            <spring.version>5.0.0.BUILD-SNAPSHOT</spring.version>
            <servlet.api.version>3.1.0</servlet.api.version>
        </properties>
    
        <repositories>
            <repository>
                <id>spring-snapshots</id>
                <name>Spring Snapshots</name>
                <url>https://repo.spring.io/libs-snapshot</url>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
        </repositories>
    
        <dependencies>
    
            <!-- Spring framework used dependencies. -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <!-- Servlet used dependencies -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>${servlet.api.version}</version>
                <scope>provided</scope>
            </dependency>
    
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>javax.servlet.jsp-api</artifactId>
                <version>2.3.1</version>
                <scope>provided</scope>
            </dependency>
    
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>1.2</version>
            </dependency>
    
            <dependency>
                <groupId>taglibs</groupId>
                <artifactId>standard</artifactId>
                <version>1.1.2</version>
            </dependency>
    
            <dependency>
                <groupId>commons-net</groupId>
                <artifactId>commons-net</artifactId>
                <version>3.3</version>
            </dependency>
    
            <!-- File upload used dependencies -->
            <dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>1.3.1</version>
            </dependency>
    
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.2</version>
            </dependency>
    
        </dependencies>
    
        <build>
            <finalName>spring-mvc-file-upload-download</finalName>
            <plugins>
    
                <!-- This plugin is used to create the war file. -->
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>2.3</version>
                    <configuration>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                    </configuration>
                </plugin>
    
                <!-- This plugin is used to deploy war file to tomcat server. -->
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                    <configuration>
                        <username>tomcat</username>
                        <password>tomcat</password>
                        <!-- update true will override the existing deployed war file in tomcat -->
                        <update>true</update>
                    </configuration>
                </plugin>
    
            </plugins>
        </build>
    </project>

10. Run Upload Files Example.

  1. Run maven clean, install and deploy the target war file to the tomcat server. Please refer to How To Deploy A Maven Project To Tomcat From Eclipse.
  2. Then you can run the example with url http://localhost:8080/SpringMVCFileUpload/upload_file/main.html.
  3. If you want to debug the example you can refer to Tomcat Remote Debugging Eclipse.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.