Spring MVC Multiple File Upload Example

Spring MVC provides out of box support for multiple file upload functionality in any application. This tutorial uses CommonsMultipartResolver and requires apache commons fileupload and apache commons io 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.6</version>
</dependency>

1. Spring MVC MultipartFile Interface

A file uploaded to a Spring MVC application will be wrapped in a MultipartFile object. All we need to do is to write a domain class with a property of type MultipartFile. This interface has methods for getting the name and content of an uploaded file e.g. getBytes(), getInputStream(), getOriginalFilename(), getSize(), isEmpty() and tranferTo().

For example, to save the uploaded file to file system, we can use the transferTo method:

File file = new File(...);
multipartFile.transferTo(file);

2. Domain class for file upload

You need to create a simple domain class with necessary attributes and one for storing files of type List<MultipartFile>.

To build this example, I have written this domain class.

public class Product implements Serializable 
{
    private static final long serialVersionUID = 74458L;

    @NotNull
    @Size(min=1, max=10)
    private String name;

    private String description;

    private List<MultipartFile> images;
    
	//getters and setters
}

3. Spring MVC multi-file upload controller

In controller class, we will get pre-populated details of uploaded files in domain class. Just fetch the details and store the files in file system or database as per application design.

@Controller
public class DemoProductController 
{
	@RequestMapping("/save-product")
	public String uploadResources( HttpServletRequest servletRequest, 
								 @ModelAttribute Product product,
								 Model model) 
	{
		//Get the uploaded files and store them
		List<MultipartFile> files = product.getImages();
        List<String> fileNames = new ArrayList<String>();
        if (null != files && files.size() > 0) 
        {
            for (MultipartFile multipartFile : files) {

                String fileName = multipartFile.getOriginalFilename();
                fileNames.add(fileName);

                File imageFile = new File(servletRequest.getServletContext().getRealPath("/image"), fileName);
                try 
                {
                    multipartFile.transferTo(imageFile);
                } catch (IOException e) 
                {
                    e.printStackTrace();
                }
            }
        }

        // Here, you can save the product details in database
        
        model.addAttribute("product", product);
        return "viewProductDetail";
	}
	
	@RequestMapping(value = "/product-input-form")
    public String inputProduct(Model model) {
        model.addAttribute("product", new Product());
        return "productForm";
    }
}

4. Spring MVC configuration changes

To support multipart request, we will need to declare multipartResolver bean in configuration file.

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="maxUploadSize" value="20848820" />
</bean>

Equivalent Java annotation configuration is :

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

Additionally, we may want to map the file storage path on server as resource. This will be spring mvc file upload directory.

<mvc:resources mapping="/image/**" location="/image/" /> 

The complete configuration file used for this example is:

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

	<context:component-scan base-package="com.howtodoinjava.demo" />
	
	<mvc:resources mapping="/image/**" location="/image/" /> 

	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
	<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
	
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>
	
	<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
	    <property name="basename" value="messages" />
	</bean>
	
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<property name="maxUploadSize" value="20848820" />
	</bean>
	
</beans>

5. Spring MVC view to upload files

I have written two JSP files. One for showing the file upload form where user will fill the other details and choose files to upload. Second where we will display the upload files with other details.

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<title>Add Product Form</title>
</head>
<body>
	<div id="global">
		<form:form commandName="product" action="save-product" method="post" enctype="multipart/form-data">
			<fieldset>
				<legend>Add a product</legend>
				<p>
					<label for="name">Product Name: </label>
					<form:input id="name" path="name" cssErrorClass="error" />
					<form:errors path="name" cssClass="error" />
				</p>
				<p>
					<label for="description">Description: </label>
					<form:input id="description" path="description" />
				</p>
				<p>
					<label for="image">Product Images: </label> 
					<input type="file" name="images" multiple="multiple"/>
				</p>
				<p id="buttons">
					<input id="reset" type="reset" tabindex="4"> 
					<input id="submit" type="submit" tabindex="5" value="Add Product">
				</p>
			</fieldset>
		</form:form>
	</div>
</body>
</html>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<title>Save Product</title>
</head>
<body>
<div id="global">
    <h4>The product has been saved.</h4>
        <h5>Details:</h5>
        Product Name: ${product.name}<br/>
        Description: ${product.description}<br/>
        <p>Following files are uploaded successfully.</p>
        <ol>
        <c:forEach items="${product.images}" var="image">
            <li>${image.originalFilename}
            <img width="100" src="<c:url value="/image/"/>${image.originalFilename}"/>
            </li>
        </c:forEach>
        </ol>
</div>
</body>
</html>

Spring MVC multiple file upload example

When we hit the browser with http://localhost:8080/springmvcexample/product-input-form, we get following screen:

Spring MVC file upload form
Spring MVC file upload form

we fill the details and submit the form and we will get the submitted details and all uploaded files in other page:

file uploaded successfully
file uploaded successfully

Drop me your questions and suggestions in comments section related to this spring mvc multipart file upload example.

Happy Learning !!

Was this post helpful?

Join 7000+ Awesome Developers

Get the latest updates from industry, awesome resources, blog updates and much more.

* We do not spam !!

12 thoughts on “Spring MVC Multiple File Upload Example”

  1. i figured out that the images are saved under
    /home/user/IdeaProjects/webstore/target/webstore-1.0-SNAPSHOT/
    while i was expecting them to be saved permanently on the project file structure i.e
    /home/user/ideaProjects/webstore/webapp/resources/images
    what could be the reason behind this as am using the same code as above

    Reply
  2. Above example need below changes to work it properly:

    1)In configuration file: Add one more location /WEB-INF/image/ as below:

    2)Under /save-product handler method, make changes in for loop as below-
    i. create image directory
    ii.create image file
    for (MultipartFile multipartFile : files) {
    String fileName = multipartFile.getOriginalFilename();
    fileNames.add(fileName);
    /*create image directory**/
    File imageDir = new File(context.getRealPath(“WEB-INF”), “image” );
    imageDir.mkdirs();
    File imageFile = new File(imageDir, fileName);
    try
    {
    /*create actual file*/
    imageFile.createNewFile();
    multipartFile.transferTo(imageFile);
    } catch (IOException e)
    {
    e.printStackTrace();
    }
    }

    And it works!!

    Reply
  3. Hi,

    I tried this code but i’m getting this error:
    an error occured in image.transferTo(imageFile): java.io.FileNotFoundException: C:\Users\x\git\workspace\.metadata\.plugins\ org.eclipse.wst.server.core\tmp1\wtpwebapps\ AdPost\C:\Users\x\Documents\AdPost\images\uploads\adpost-login.PNG (The filename, directory name, or volume label syntax is incorrect)

    this is the code im using

    if(files != null && files.size() > 0){
    
    for(MultipartFile image:files){
    	String fileName = image.getOriginalFilename();
    	
    	fileNames.add(fileName);
    	
    	File imageFile = new File(request.getServletContext() 
    		.getRealPath("C:/Users/x/Documents/AdPost/images/uploads"), fileName);
    	image.transferTo(imageFile);					
    	
    }
    
    Reply
    • files != null && files.size() > 0

      I found this not works. Whatever the amount of files is 0 or 1, the files.size() is always 1. And other file numbers are normal as expected.

      Reply
  4. Hello, I tried this example. However, though I selected multiple files, only one reaches to controller i.e. List files = product.getImages(); has size of 1 only.

    It should hold all the images that I uploaded. Can you advise if I could be missing something?

    Thanks,
    Ashish

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and related technologies, the best practices, algorithms, and interview questions.