Monday 17 February 2014

Maven + Spring MVC Multiple File Upload example

In this tutorial, we show you how to develop a Spring MVC Multiple File Upload in Spring 3 MVC based application.

How to upload a file in Spring MVC and save it to a directory' .Spring supports MultipartResolver to handle file upload capabilities in a web application. We will add a 'MultipartResolver' bean to our spring configuration file to take advantage of Apache Commons upload library to handle upload in application.

The requirement is simple. We have a form which displays file input component. User selects a file and upload it. Also its possible to add more file input components using Add button. Once the files are selected and uploaded, the file names are displayed on success page.




Project Structure


Create a simple Maven WebApplication and import it to eclipse, now add required dependencies and controller file as shown in the later part of this tutorial.





Below is the Content for Pom.xml


We need to add dependencies for Apache Common File upload and Apache Common IO libraries. The spring’s CommonsMultipartResolver class internal uses these library to handle uploaded content.

Add following dependencies in your maven based project to add File upload feature


<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mahesh.common</groupId>
  <artifactId>SpringMVC_Form_Multiple_Upload</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>SpringMVC Form Upload Webapp</name>
  <url>http://maven.apache.org</url>
 
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
   
    <!-- Spring framework -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>3.1.2.RELEASE</version>
    </dependency>

    <!-- Spring MVC framework -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>3.1.2.RELEASE</version>
    </dependency>
   
    <!-- Apache Commons Upload -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.2.2</version>
    </dependency>

    <!-- Apache Commons Upload -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.3.2</version>
    </dependency>

    <!-- JSTL -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.1.2</version>
    </dependency>
   
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
   
    <dependency>
        <groupId>taglibs</groupId>
        <artifactId>standard</artifactId>
        <version>1.1.2</version>
    </dependency>

  </dependencies>
  <build>
    <finalName>SpringMVC</finalName>
  </build>
</project>





Below is the Content for Controller Class FileUploadController.java


This is a simple spring controller class having two mappings, the firsts one returns a jsp to show the uploading form. In second method all code is written to how to get a multipart file object from FileUploadForm and how to write it to a directory.


package com.mahesh.common.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.mahesh.common.model.FileUploadForm;
import com.mahesh.common.validator.FileUploadValidator;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
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;

@Controller
public class FileUploadController {

    private String saveDirectory = "D:/Upload/";
   
    @Autowired 
    FileUploadValidator fileValidator;

    @RequestMapping(value = "/fileUploadForm", method = RequestMethod.GET)
    public String displayForm() {
        return "file_upload_form";
    }

    @RequestMapping(value = "/fileUpload", method = RequestMethod.POST)
    public String save(@ModelAttribute("uploadForm") FileUploadForm uploadForm, BindingResult result, Model map) throws IllegalStateException, IOException {

        List<MultipartFile> files = uploadForm.getFiles();

        List<String> fileNames = new ArrayList<String>();
       
        fileValidator.validate(uploadForm, result);
       
        if(result.hasErrors()){
            return "file_upload_form";
        }

        if(null != files && files.size() > 0) {
            for (MultipartFile multipartFile : files) {

                String fileName = multipartFile.getOriginalFilename();

                if(!"".equalsIgnoreCase(fileName)){
                    fileNames.add(fileName);
                    multipartFile.transferTo(new File(saveDirectory + multipartFile.getOriginalFilename()));
                }
            }
        }

        map.addAttribute("files", fileNames);
        return "file_upload_success";
    }
}


Below is the Content for Model – Form Object FileUploadForm.java

 
Create a Java bean which acts as Model/Form object for our Spring application. This bean contains a List of org.springframework.web.multipart.MultipartFile objects. Spring framework provides a useful class MultipartFile which can be used to fetch the file content of uploaded file. Apart from its content, the MultipartFile object also gives you other useful information such as filename, file size etc.



package com.mahesh.common.model;

import java.util.List;

import org.springframework.web.multipart.MultipartFile;

public class FileUploadForm {

    private List<MultipartFile> files;

    public List<MultipartFile> getFiles() {
        return files;
    }

    public void setFiles(List<MultipartFile> files) {
        this.files = files;
    }
}



Below is the Content for Validation class to validate the uploading file FileUploadValidator.java

 This is another simple java class having code to validate if the user uploaded a file before submitting the form or not.


package com.mahesh.common.validator;

import java.util.List;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.multipart.MultipartFile;

import com.mahesh.common.model.FileUploadForm;

@Component
@Scope("prototype")
public class FileUploadValidator implements Validator{

    public boolean supports(Class clazz) {
        //just validate the FileUpload instances
        return FileUploadForm.class.isAssignableFrom(clazz);

    }

    public void validate(Object target, Errors errors) {
       
        FileUploadForm uploadForm = (FileUploadForm)target;
        List<MultipartFile> files = uploadForm.getFiles();
       
        if(files.size() > 0){
            for (MultipartFile multipartFile : files) {

                String fileName = multipartFile.getOriginalFilename();

                if("".equalsIgnoreCase(fileName.trim())){
                    errors.rejectValue("files", "required.fileUpload");
                   
                }
            }
        }
    }
   
}


Below is the Content for file_upload_form.jsp to display file upload form


This is a simple jsp file containing a form, the form is having a file input field to make user select and upload a file. Do not forget to set enctype="multipart/form-data", this w'll make the file object to be returned as a multipart object.


<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
    <title>Spring MVC Multiple File Upload</title>
<style>
    body {font-family: "Trebuchet MS";}
    h1 {font-size: 1.5em;}
.error {
    color: #ff0000;
}
.errorblock{
    color: #000;
    background-color: #ffEEEE;
    border: 3px solid #ff0000;
    padding:8px;
    margin:16px;
}

</style>

<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>

<script>
$(document).ready(function() {

    $('#addFile').click(function() {
        var fileIndex = $('#fileTable tr').children().length;
        $('#fileTable').append(
                '<tr><td>'+
                '    <input type="file" name="files['+ fileIndex +']" />'+
                '</td></tr>');
    });
   
});
</script>
</head>
<body>
<h1>Spring MVC Multiple File Upload example</h1>

<form:form method="post" action="fileUpload.htm"
        modelAttribute="uploadForm" enctype="multipart/form-data">
       
    <form:errors path="*" cssClass="errorblock" element="div"/>

    <p>Select files to upload. Press Add button to add more files.</p>

    <input id="addFile" type="button" value="Add File" />
    <table id="fileTable">
        <tr>
            <td><input name="files[0]" type="file" /></td>
        </tr>
        <tr>
            <td><input name="files[1]" type="file" /></td>
        </tr>
    </table>
    <br/><input type="submit" value="Upload" />
</form:form>
</body>
</html>


Below is the Content for file file_upload_success.jsp to display Uploaded File Details


<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>Spring MVC Multiple File Upload</title>
<style>
body { font-family: "Trebuchet MS"; }
h1 { font-size: 1.5em; }
</style>
</head>
<body>
    <h1>Spring MVC Multiple File Upload example</h1>
    <p>Following files are uploaded successfully.</p>
    <ol>
        <c:forEach items="${files}" var="file">
            <li>${file}</li>
        </c:forEach>
    </ol>
</body>
</html>


Below is the Content for index.jsp to forward to file_upload_form.jsp


<jsp:forward page="fileUploadForm.htm"></jsp:forward>

Below is the Content for message.properties to display errors


required.fileUpload = Please select a file!

Below is the Content for Spring Configuration file mvc-dispatcher-servlet.xml


In Spring configuration we defined fileValidator bean to validate user input and a 'multipartResolver' bean to take advantage of apache commons uploading capabilities. This will make sure Spring handles the file upload correctly using CommonsMultipartResolver class.


<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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

  <context:annotation-config />
  <context:component-scan base-package="com.mahesh.common.controller"/>
  <context:component-scan base-package="com.mahesh.common.validator"/>

  <bean id="multipartResolver"
  class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
 
  <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="message" />
    </bean>

  <bean id="jspViewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/pages/" />
        <property name="suffix" value=".jsp" />
  </bean>

</beans>

Below is the Content for web.xml where configured DispatcherServlet

 


<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

  <display-name>Spring Web MVC Application</display-name>
 
  <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
 
  <servlet>
      <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
 
  <servlet-mapping>
     <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>*.htm</url-pattern>
  </servlet-mapping>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
  </context-param>
 
  <listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>
 
 
</web-app>







Run the Application by Deploying the SpringMVC.war in Web/Application Server.

Url: http://localhost:8080/SpringMVC/


Render a file upload component.



Display the error message if user didn’t select a file to upload while clicking on the upload button.




If file upload successful, display the uploaded file name.










No comments:

Post a Comment