Spring 4 MVC File Upload Example

September 25, 2015 | Updated last October, 2015 | 5911 views | Comments

Upload files with Spring 4 MVC Framework. Take advantage of it's easy-to-use ModelMap() and ModelAndView() classes to display information on the front-end, and let Spring handle the file upload by using transferTo() class at the back-end. This is perfect for web applications requiring an upload image function.

 

Built and tested with the following:

  • Eclipse Juno IDE
  • Apache Tomcat 7.0.47
  • JDK 1.7.0
  • Maven 3.0.4
  • Spring Web-MVC Framework 4.2.2
    • Configuration: XML
    • Url Mapping: Annotation
  • Multipart upload file.

 

Task: Create a Spring application that will allow any user to upload a JPG or GIF image. The file size must not exceed 1 MB.


Summary

  • Step 1. Set up a Spring WebMVC Framework 4 Application.
  • Step 2. Prepare the view file.
  • Step 3. Add new dependencies.
  • Step 4. Add MultipartResolver bean to the dispatcher.
  • Step 5. Map the Home and Upload (GET method) pages.
  • Step 6. Create the Class that will process the file upload.
  • Step 7. Map the "/upload" POST method request.

Highlights

Front-end (HTML Form)

<form method="POST" enctype="multipart/form-data" action="upload">
    <p>File to upload: <input type="file" name="file"></p>
    <p><input type="submit" value="Upload"> Press here to upload the file!</p>
</form>

 

Back-end (JAVA Class)

@RequestMapping(value="/upload", method=RequestMethod.POST)
    public ModelAndView handleFileUpload(@RequestParam("file") MultipartFile file) {
    try {
        /**
         * Set the path where to save the file.
         * ex. "C:\\images\\" + file.getOriginalFilename() //win
         * ex. "/images/" + file.getOriginalFilename() //nix
         */
        file.transferTo(new File(file.getOriginalFilename()));
        //successful
    } catch (IllegalStateException e) {
        //error
    } catch (IOException e) {
        //error
    }

    ModelAndView model = new ModelAndView();
    //set message
    model.setViewName("index");

    return model;
}

 

Settings (spring-servlet.xml)

<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"/>

 

Settings (pom.xml)

<!-- Apache Commons FileUpload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

Step 1. Set up a Spring WebMVC Framework 4 Application.

Instructions on How to Create A Spring 4 MVC application can be found on the JAVA tutorial Spring 4 MVC Hello World Annotation Example.

Although it is better to first read and understand the given sample above, there are also some options to quickly set up the project. To clone, download, or import it's source code, go directly to this link.

It is important to have the Spring WebMVC application running correctly before continuing with the next steps.

Spring 4 MVC Hello World Annotation Example Final Project Structure

A working Spring 4 MVC Hello World Annotation Example screenshot.

Continue below if your application is running correctly like what was shown on the above image.

 

Step 2. Prepare the view file.

Only a single jsp file will be used on this application, it will handle both the form and the result pages.

Step 2.1. Rename hello.jsp.

Rename hello.jsp to index.jsp and put the following "upload form HTML code" after ${ message } tag.

<div>
        <form method="POST" enctype="multipart/form-data" action="upload">
            <p>File to upload: <input type="file" name="file"></p>
            <p><input type="submit" value="Upload"> Press here to upload the file!</p>
        </form>
    </div>

Note: The parameter file was created. This value must match the variable at the back-end later. Encryption type (enctype) is also set to multipart/form-data, this allows a file to be submitted through POST method. The action is set to upload, this link will be mapped later to the back-end that will process the upload request.

Step 2.2. Change the page title.

Change the &ly;title> value, too. To make it more appropriate with the upload example, have the following code into it.

<title>Spring 4 MVC File Upload Example</title>

 

Full code of index.jsp file.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!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=ISO-8859-1">
<title>Spring 4 MVC File Upload Example</title>
</head>
<body>
    <h1>${ message }</h1>
    
    <div>
        <form method="POST" enctype="multipart/form-data" action="upload">
            <p>File to upload: <input type="file" name="file"></p>
            <p><input type="submit" value="Upload"> Press here to upload the file!</p>
        </form>
    </div>
</body>
</html>

/src/main/webapp/WEB-INF/jsp/index.jsp

 

Step 3. Add new dependency.

Open pom.xml, add "Apache Commons FileUpload" dependency.

Apache Commons FileUpload

This will add multipart file upload capability to the web application.

        <!-- Apache Commons FileUpload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>

 

Full code of pom.xml file.

<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.consistentcoder</groupId>
    <artifactId>spring-4-mvc-hello-world-annotation</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>spring 4 mvc hello world annotation</name>
    
    <dependencies>
        <!-- Spring Framework -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.2.2.RELEASE</version>
        </dependency>
        
        <!-- Apache Commons FileUpload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>
</project>

/pom.xml

 

Step 4. Add MultipartResolver bean to the dispatcher.

Add the following code inside spring-servlet.xml.

<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"/>

 

Full code of spring-servlet.xml.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-4.2.xsd
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">

    <context:component-scan base-package="com.consistentcoder.controllers" />
    <mvc:annotation-driven />

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
    
    <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"/>
</beans>

/src/main/webapp/WEB-INF/spring-servlet.xml

 

Step 5. Map the Home and Upload (GET method) pages.

Step 5.1. Catch GET request to "/upload" page.

The main page is already created, and uploading files requires a POST request method, instead of showing an exception error page, just use the "home/index page mapping controller" if the in incoming request is through the GET method. In short, show the upload form if a user directly browsed the "/upload" link.

Open Main.java Class. Change @RequestMapping(value = "/", method = RequestMethod.GET), with the following.

@RequestMapping(value = { "/","/upload" }, method = RequestMethod.GET)

 

Remember also that there is only one view file, and that is index.jsp. Use that in all related view file on the Controller.

Just change return "hello" with the following.

return "index"

 

It would also be nice if the Home Page Message is changed accordingly. Something like the message below.

model.addAttribute("message", "Spring 4 MVC File Upload Example");

 

Current full Main.java Class code.

There is still one mapping that will be added later, the one that will handle the file upload process through POST method. This is not the final Controller Class yet.

package com.consistentcoder.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class Main {
    @RequestMapping(value = { "/","/upload" }, method = RequestMethod.GET)
	public String index(ModelMap model) {
	
		model.addAttribute("message", "Spring 4 MVC File Upload Example");
		return "index";
	}
}

/src/main/java/com/consistentcoder/constrollers/Main.java

 

By now, the file upload form should be accessible. When the server has been started, the Home Page should be like the image below.

 

Since the /upload link that will process the file upload through the POST method is not yet created, clicking the upload button will show a page like below.

 

On the other hand, GET request method was mapped with the home page, and because of that, when the link /upload was directly entered and hit on the browser, the home page will also be presented.

 

Step 6. Create the Class that will process the file upload.

Tutorials:
Create a New Package on Eclipse IDE
Create a New JAVA Class on Eclipse IDE

 

Step 6.1. Create a new package where the Class will be created

Create a new package, name it com.consistentcoder.models.

 

Step 6.2. Create the file upload Class file

Create a new Class, name it FileUpload, put the following code on it.

package com.consistentcoder.models;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import org.springframework.web.multipart.MultipartFile;

public class FileUpload {
    private static final String[] ALLOWED_FILE_TYPES = {"image/jpeg", "image/jpg", "image/gif"};
    private static final Long MAX_FILE_SIZE = 1048576L; //1MB
    private static final String UPLOAD_FILE_PATH = "/opt/images/";
    
    public String process(MultipartFile file) {
        if (!file.isEmpty()) {
            String contentType = file.getContentType().toString().toLowerCase();
            if (isValidContentType(contentType)) {
                if (belowMaxFileSize(file.getSize())) {
                    String newFile = UPLOAD_FILE_PATH + file.getOriginalFilename();
                    try {
                        file.transferTo(new File(newFile));
                        return "You have successfully uploaded " + file.getOriginalFilename() + "!";
                    } catch (IllegalStateException e) {
                        return "There was an error uploading " + file.getOriginalFilename() + " => " + e.getMessage();
                    } catch (IOException e) {
                        return "There was an error uploading " + file.getOriginalFilename() + " => " + e.getMessage();
                    }
                } else {
                    return "Error. " + file.getOriginalFilename() + " file size (" + file.getSize() + ") exceeds " + MAX_FILE_SIZE + " limit.";
                }
            } else {
                return "Error. " + contentType + " is not a valid content type.";
            }
        } else {
            return "Error. No file choosen.";
        }
    }
    
    private Boolean isValidContentType(String contentType) {
        if (!Arrays.asList(ALLOWED_FILE_TYPES).contains(contentType)) {
            return false;
        }
        
        return true;
    }
    
    private Boolean belowMaxFileSize(Long fileSize) {
        if (fileSize > MAX_FILE_SIZE) {
            return false;
        }
        
        return true;
    }
}

/src/main/java/com/consistentcoder/models/FileUpload.java

 

Allowed file types can easily be configured with the variable ALLOWED_FILE_TYPES. JPG and GIF images will be allowed in this example.

private static final String[] ALLOWED_FILE_TYPES = {"image/jpeg", "image/jpg", "image/gif"};

 

Allowed maximum file size in bytes is set on the variable MAX_FILE_SIZE. In this example, up to 1 MB file size will be allowed.

private static final Long MAX_FILE_SIZE = 1048576L; //1MB

 

The folder where the uploaded files will be saved is declared on the variable UPLOAD_FILE_PATH. To maintain a good application file size, it is a good decision to save uploaded files outside the application. Uploaded files in this example will be saved on /opt/images/. Make sure the folder is existing. It's windows equivalent folder is C:\opt\images\.

private static final String UPLOAD_FILE_PATH = "/opt/images/";

 

There are three check points created, each one has it's basic purpose. It can also be easily adjusted if a check point needs to be added or removed. It is however, a good practice to have these basic check points.

  • if (!file.isEmpty()) {
    - Check if the uploaded multipart file is not empty.
  • if (isValidContentType(contentType)) {
    - Check if the uploaded file is within the configured allowed content types.
  • if (belowMaxFileSize(file.getSize())) {
    - Check if the uploaded file is not over the required maximum file size.

If the file upload gets through the check points, the application will try to transfer the uploaded file to where the UPLOAD_FILE_PATH is pointed to. If the transfer is achieved, a success message will be returned, otherwise, an Exception message will be the output.

 

Step 7. Map the "/upload" POST method request.

Process the file upload request by adding a new method with POST request method to Main.java Class. Open that class and put the following code below the index method.

@RequestMapping(value="/upload", method=RequestMethod.POST)
    public ModelAndView handleFileUpload(@RequestParam("file") MultipartFile file) {
        
        ModelAndView model = new ModelAndView();
        FileUpload fileUpload = new FileUpload();
        model.addObject("message", fileUpload.process(file));
        model.setViewName("index");
        
        return model;
    }

Take note of the parameter that was created on the index.jsp view file is matched in this method.

The set parameter name="file" in this front-end code.

input type="file" name="file"

Is matched in this back-end code @RequestParam("file").

handleFileUpload(@RequestParam("file") MultipartFile file)

 

Final full Main.java Class code.

package com.consistentcoder.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.consistentcoder.models.FileUpload;

@Controller
public class Main {
    @RequestMapping(value = { "/","/upload" }, method = RequestMethod.GET)
	public String index(ModelMap model) {
	
		model.addAttribute("message", "Spring 4 MVC File Upload Example");
		return "index";
	}
    
    @RequestMapping(value="/upload", method=RequestMethod.POST)
    public ModelAndView handleFileUpload(@RequestParam("file") MultipartFile file) {
        
        ModelAndView model = new ModelAndView();
        FileUpload fileUpload = new FileUpload();
        model.addObject("message", fileUpload.process(file));
        model.setViewName("index");
        
        return model;
    }
}

/src/main/java/com/consistentcoder/constrollers/Main.java

 

That's all!

Spring 4 MVC File Upload Example application has been developed.

 

Final Project Structure

 

What's Next? Test the application.

Start your server and browse this link. http://localhost:8080/spring-4-mvc-hello-world-annotation/upload/

 

Upload a JPG file.

 

Upload a TXT file.

 

Upload a JPG file that is more than the 1 MB file limit size.

 

Click the upload button without choosing any file.


References: