Spring MVC file upload example Commons FileUpload
This article will shows you how to use CommonsMultipartResolver to handle file upload in Spring MVC web application.
Tools used :
- Spring 4.3.5.RELEASE
- commons-fileupload 1.3.2
- Maven 3
- Tomcat 7 or 8 and Jetty 8, 9
For StandardServletMultipartResolver – file upload using Servlet 3.0 multipart request parsing, please refer to this Spring MVC file upload example
1. Project Structure
A standard Maven project structure.
2. Project Dependency
2.1 You need commons-fileupload.jar
<!-- Apache Commons Upload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.2</version> </dependency>
2.2 Complete Maven Pom 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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mkyong</groupId> <artifactId>spring-mvc-file-upload</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>Spring MVC file upload</name> <properties> <jdk.version>1.8</jdk.version> <spring.version>4.3.5.RELEASE</spring.version> <jstl.version>1.2</jstl.version> <servletapi.version>3.1.0</servletapi.version> <commons.fileupload.version>1.3.2</commons.fileupload.version> <logback.version>1.1.3</logback.version> <jcl.slf4j.version>1.7.12</jcl.slf4j.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <!-- compile only, deployed container will provide this --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servletapi.version}</version> <scope>provided</scope> </dependency> <!-- Logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${jcl.slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <!-- Apache Commons Upload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>${commons.fileupload.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>${jdk.version}</source> <target>${jdk.version}</target> </configuration> </plugin> <!-- embedded Jetty server, for testing --> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.2.11.v20150529</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <webApp> <contextPath>/spring4upload</contextPath> </webApp> </configuration> </plugin> <!-- configure Eclipse workspace --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-eclipse-plugin</artifactId> <version>2.9</version> <configuration> <downloadSources>true</downloadSources> <downloadJavadocs>true</downloadJavadocs> <wtpversion>2.0</wtpversion> <wtpContextName>/spring4upload</wtpContextName> </configuration> </plugin> </plugins> </build> </project>
$ mvn dependency:tree [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Spring MVC file upload 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ spring-mvc-file-upload --- [INFO] com.mkyong:spring-mvc-file-upload:war:1.0-SNAPSHOT [INFO] +- org.springframework:spring-webmvc:jar:4.3.5.RELEASE:compile [INFO] | +- org.springframework:spring-aop:jar:4.3.5.RELEASE:compile [INFO] | +- org.springframework:spring-beans:jar:4.3.5.RELEASE:compile [INFO] | +- org.springframework:spring-context:jar:4.3.5.RELEASE:compile [INFO] | +- org.springframework:spring-core:jar:4.3.5.RELEASE:compile [INFO] | +- org.springframework:spring-expression:jar:4.3.5.RELEASE:compile [INFO] | \- org.springframework:spring-web:jar:4.3.5.RELEASE:compile [INFO] +- javax.servlet:jstl:jar:1.2:compile [INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided [INFO] +- org.slf4j:jcl-over-slf4j:jar:1.7.12:compile [INFO] | \- org.slf4j:slf4j-api:jar:1.7.12:compile [INFO] +- ch.qos.logback:logback-classic:jar:1.1.3:compile [INFO] | \- ch.qos.logback:logback-core:jar:1.1.3:compile [INFO] \- commons-fileupload:commons-fileupload:jar:1.3.2:compile [INFO] \- commons-io:commons-io:jar:2.2:compile
3. CommonsMultipartResolver
Create a multipartResolver bean.
package com.mkyong; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; 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({"com.mkyong"}) public class SpringWebMvcConfig extends WebMvcConfigurerAdapter { private int maxUploadSizeInMb = 5 * 1024 * 1024; // 5 MB @Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setViewClass(JstlView.class); viewResolver.setPrefix("/WEB-INF/views/jsp/"); viewResolver.setSuffix(".jsp"); return viewResolver; @Bean public CommonsMultipartResolver multipartResolver() { CommonsMultipartResolver cmr = new CommonsMultipartResolver(); cmr.setMaxUploadSize(maxUploadSizeInMb * 2); cmr.setMaxUploadSizePerFile(maxUploadSizeInMb); //bytes return cmr;
Done, the file upload configuration is set up properly.
4. ServletInitializer
A standard Servlet initializer, nothing special here.
package com.mkyong; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class MyWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringWebMvcConfig.class}; @Override protected String[] getServletMappings() { return new String[]{"/"}; @Override protected Class<?>[] getRootConfigClasses() { return null;
5. Spring Controller
5.1 The uploaded files will map to MultipartFile
package com.mkyong.controller; import com.mkyong.model.UploadForm; import org.springframework.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.StringJoiner; @Controller public class UploadController { // save uploaded file to this folder private static String UPLOADED_FOLDER = "F://temp//"; @GetMapping("/") public String index() { return "upload"; @PostMapping("/upload") public String multiFileUpload(@ModelAttribute UploadForm form, RedirectAttributes redirectAttributes) { StringJoiner sj = new StringJoiner(" , "); for (MultipartFile file : form.getFiles()) { if (file.isEmpty()) { continue; //next pls try { byte[] bytes = file.getBytes(); Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename()); Files.write(path, bytes); sj.add(file.getOriginalFilename()); } catch (IOException e) { e.printStackTrace(); String uploadedFileName = sj.toString(); if (StringUtils.isEmpty(uploadedFileName)) { redirectAttributes.addFlashAttribute("message", "Please select a file to upload"); } else { redirectAttributes.addFlashAttribute("message", "You successfully uploaded '" + uploadedFileName + "'"); return "redirect:/uploadStatus"; @GetMapping("/uploadStatus") public String uploadStatus() { return "uploadStatus";
5.2 Maps HTML values into this model.
package com.mkyong.model; import org.springframework.web.multipart.MultipartFile; public class UploadForm { MultipartFile[] files; public MultipartFile[] getFiles() { return files; public void setFiles(MultipartFile[] files) { this.files = files;
6. Spring JSP Views
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <html> <body> <h1>Spring MVC multi files upload example</h1> <form:form method="POST" action="${pageContext.request.contextPath}/uploadMulti" modelAttribute="uploadForm" enctype="multipart/form-data"> <input type="file" name="files" /><br/> <input type="file" name="files" /><br/> <input type="file" name="files" /><br/><br/> <input type="submit" value="Submit" /> </form:form> </body> </html>
<html> <body> <h1>Upload Status</h1> <h2>Message : ${message}</h2> </body> </html>
7. Max upload size exceeded
To handle the max upload size exceeded exception, declares a @ControllerAdvice and catch the MaxUploadSizeExceededException
package com.mkyong.exception; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.multipart.MaxUploadSizeExceededException; import org.springframework.web.servlet.mvc.support.RedirectAttributes; @ControllerAdvice public class GlobalExceptionHandler { //commons-fileupload @ExceptionHandler(MaxUploadSizeExceededException.class) public String handleError2(MaxUploadSizeExceededException e, RedirectAttributes redirectAttributes) { redirectAttributes.addFlashAttribute("message", e.getCause().getMessage()); return "redirect:/uploadStatus";
8. DEMO
8.1 Get the source code below and test with the embedded Jetty server mvn jetty:run. Context is /spring4upload
project $ mvn jetty:run //... [INFO] Started o.e.j.m.p.JettyWebAppContext@341672e{/spring4upload, file:/SpringMVCUploadExample/src/main/webapp/,AVAILABLE}{file:/SpringMVCUploadExample/src/main/webapp/} [WARNING] !RequestLog [INFO] Started ServerConnector@3ba1308d{HTTP/1.1}{0.0.0.0:8080} [INFO] Started @3743ms [INFO] Started Jetty Server [INFO] Starting scanner at interval of 10 seconds.
8.2 Access http://localhost:8080/spring4upload , select a few of files and upload it.
8.3 Result.
8.3 If you upload a total file size bigger than 10mb, this exception page will be displayed.
If you deployed the web app to Tomcat, and unable to catch the file size exceeded exception, this may cause by the Tomcat maxSwallowSize setting. Read this – Spring file upload and connection reset issue
8. Download Source Code
References
- Spring Uploading Files
- Spring’s multipart (file upload) support
- Spring MVC file upload example
- Spring file upload and connection reset issue
From:一号门
COMMENTS