Spring MVC Multipart file upload Example with Validator - Spring MVC Tutorial

Overview

In this tutorial, we show you how to create Multiple File Uploads in Spring MVC and validating it. We use the commons-fileupload 1.3.1 lib with method CommonsMultipartFile to upload multiple files and the validation-api 1.1.0.Final lib to validate the uploaded files.
Follow the steps mentioned below to buid this example

Spring MVC Multipart file upload Example with Validator

Watch video Tutorials

Project Structure



Project Structure Spring MVC Multipart file upload Example

How to Create the Maven Project

  • Launch Eclipse IDE.
  • Go to File-> New-> Others... Select Maven Project under Maven category then click Next.
  • In New Maven Project wizard, select "Create a simpel project(skip archetype selection)" and click on Next
  • In next wizard, type "com.jackrutorial" in the "Group ID:" field
  • Type "SpringMvcUpload" in the "Artifact Id:" field
  • Packaging -> War
  • Click Finish.

Maven Dependencies

We specify the dependency for the spring-webmvc version 4.3.0.RELEASE, jstl v1.2 and javax.servlet-api 3.1.0 to build Web MVC. We also include the commons-fileupload v1.3.1 which is used to upload a MultipartFile and the validation-api v1.1.0.Final to create a Validator.
The updated pom.xml file will have the following code:
<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.jackrutorial</groupId>
 <artifactId>SpringMvcUpload</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging>

 <dependencies>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>4.3.0.RELEASE</version>
  </dependency>
  <dependency>
   <groupId>jstl</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
  </dependency>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
   <scope>provided</scope>
  </dependency>
  <dependency>
   <groupId>commons-fileupload</groupId>
   <artifactId>commons-fileupload</artifactId>
   <version>1.3.1</version>
  </dependency>
  <dependency>
   <groupId>javax.validation</groupId>
   <artifactId>validation-api</artifactId>
   <version>1.1.0.Final</version>
  </dependency>
 </dependencies>

 <build>
  <pluginManagement>
   <plugins>
    <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-war-plugin</artifactId>
     <version>2.4</version>
     <configuration>
      <warSourceDirectory>src/main/webapp</warSourceDirectory>
      <failOnMissingWebXml>false</failOnMissingWebXml>
     </configuration>
    </plugin>
   </plugins>
  </pluginManagement>
 </build>
</project>

Configure Web Application

Create a WebConfig class under com.jackrutorial.config package and write the following code in it.
package com.jackrutorial.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
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.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = { "com.jackrutorial" })
public class WebConfig extends WebMvcConfigurerAdapter {

 @Bean
 public InternalResourceViewResolver viewResolver() {
  InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
  viewResolver.setViewClass(JstlView.class);
  viewResolver.setPrefix("/WEB-INF/jsp/");
  viewResolver.setSuffix(".jsp");

  return viewResolver;
 }

 @Bean
 public ResourceBundleMessageSource messageSource() {
  ResourceBundleMessageSource rb = new ResourceBundleMessageSource();
  rb.setBasenames(new String[] { "validation" });

  return rb;
 }
 
 @Bean(name="multipartResolver")
 public CommonsMultipartResolver getResolver() {
  CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
  //set max upload size per file is 20mb
  commonsMultipartResolver.setMaxUploadSizePerFile(20*1024*1024);
  
  return commonsMultipartResolver;
 }
}
The CommonsMultipartResolver saves temporary files to the servlet container’s temporary directory. We restrict you to a maximum 20 MB upload file size by set commonsMultipartResolver.setMaxUploadSizePerFile(20*1024*1024);
Create a WebInitializer class extends AbstractAnnotationConfigDispatcherServletInitializer under com.jackrutorial.config package and write the following code in it.
WebInitializer.java
package com.jackrutorial.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

 @Override
 protected Class<?>[] getRootConfigClasses() {
  return new Class[] { WebConfig.class};
 }

 @Override
 protected Class<?>[] getServletConfigClasses() {
  // TODO Auto-generated method stub
  return null;
 }

 @Override
 protected String[] getServletMappings() {
  return new String[] { "/" };
 }
}

Model

Create a FileUpload class under com.jackrutorial.model package and write the following code in it.
package com.jackrutorial.model;

import org.springframework.web.multipart.commons.CommonsMultipartFile;

public class FileUpload {
 private CommonsMultipartFile[] files;

 public CommonsMultipartFile[] getFiles() {
  return files;
 }

 public void setFiles(CommonsMultipartFile[] files) {
  this.files = files;
 }
}

Validator

Create a @Component FileValidator implements the org.springframework.validation.Validator, overrides the two methods supports and validate as follow below.
package com.jackrutorial.validation;

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.jackrutorial.model.FileUpload;

@Component
public class FileValidator implements Validator {

 public boolean supports(Class<?> clazz) {
  return FileUpload.class.isAssignableFrom(clazz);
 }

 public void validate(Object target, Errors errors) {
  FileUpload fileUpload = (FileUpload) target;
  
  CommonsMultipartFile[] commonsMultipartFiles = fileUpload.getFiles();
  
  for(CommonsMultipartFile multipartFile : commonsMultipartFiles) {
   if(multipartFile.getSize() == 0) {
    errors.rejectValue("files", "missing.file");
   }
  }
 }

}
The validator above is used to validate if the uploaded files are not empty. If the files are empty, we reject the value and show the "No file choose" message.

Validator Messages

Create the validation.properties under the src/main/resources/ folder.
missing.file=No file choose

Upload Controller

Create a UploadController class under com.jackrutorial.controller package and write the following code in it.
package com.jackrutorial.controller;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
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.commons.CommonsMultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.jackrutorial.model.FileUpload;
import com.jackrutorial.validation.FileValidator;

@Controller
@RequestMapping(value="/")
public class UploadController {
 
 @Autowired
 FileValidator fileValidator;

 @RequestMapping(value="/uploadPage", method=RequestMethod.GET)
 public ModelAndView uploadPage() {
  ModelAndView model = new ModelAndView("upload_page");
  model.addObject("formUpload", new FileUpload());
  
  return model;
 }
 
 @RequestMapping(value="/upload", method=RequestMethod.POST)
 public ModelAndView upload(@ModelAttribute("formUpload") FileUpload fileUpload, BindingResult result) throws IOException {
  //validate file upload
  fileValidator.validate(fileUpload, result);
  
  if(result.hasErrors()) {
   return new ModelAndView("upload_page");
  }
  
  return new ModelAndView("success", "fileNames", processUpload(fileUpload));
 }
 
 private List<String> processUpload(FileUpload files) throws IOException{
  List<String> fileNames = new ArrayList<String>();
  
  CommonsMultipartFile[] commonsMultipartFiles = files.getFiles();
  
  for(CommonsMultipartFile multipartFile : commonsMultipartFiles) {
   FileCopyUtils.copy(multipartFile.getBytes(), new File("C:\\upload\\" + multipartFile.getOriginalFilename()));
   fileNames.add(multipartFile.getOriginalFilename());
  }
  
  return fileNames;
 }
}

Views


Create upload_page.jsp file under src\main\webapp\WEB-INF\jsp\ folder and write the following code in it.
upload_page.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>    
    
<!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>Upload Page</title>
</head>
<body>
 <spring:url value="/upload" var="uploadURL" />
 <form:form modelAttribute="formUpload" method="post" action="${uploadURL }" enctype="multipart/form-data" >
  <form:input path="files" type="file" multiple="multiple" />
  <form:errors path="files" cssStyle="color: red" />
  
  <button type="submit">Upload</button>
 </form:form>
</body>
</html>
Create success.jsp file under src\main\webapp\WEB-INF\jsp\ folder and write the following code in it.
success.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>    
    
<!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>Success</title>
</head>
<body>
 <c:forEach items="${fileNames }" var="fileName">
  File <b>${fileName }</b> uploaded sucessfully<br/>
 </c:forEach>
</body>
</html>

Buid and Deploy

  • Right click this project
  • Select Run As -> Maven clean
  • Right click this project
  • Select Run As -> Maven install

Configuring Apache Tomcat 7

  • Under Servers tab, click link "No servers are available. Click this link to create a new server ...", select Apache tomcat 7
  • Click Finish
Configuring Apache Tomcat 7
Configuring Apache Tomcat 7
  • Right click "Tomcat v7.0 Server at localhost [Stopped, Republish]", select "Add and Remove ..."
  • Add SpringMvcUpload project, then Click Finish
  • Open server.xml file under Servers Folder
  • Find line
<Context docBase="{WORK_LOCATION}\SpringMvcUpload\target\SpringMvcUpload-0.0.1-SNAPSHOT\" path="/SpringMvcUpload" reloadable="true" source="org.eclipse.jst.jee.server:SpringMvcCRUDExample"  />
Update its as below:
<Context docBase="{WORK_LOCATION}\SpringMvcUpload\target\SpringMvcUpload-0.0.1-SNAPSHOT\" path="/SpringMvcUpload" reloadable="true" />

Run application & Check result

Start Apache Tomcat from Eclipse IDE.
Type the following URLs in browser's address bar to open the upload page from.
http://localhost:8080/SpringMvcUpload/uploadPage
upload files page
No file choose
No file choose
Files uploaded sucessfully
upload files page successfully
Previous Post
Next Post

post written by: