In this post we’ll see a Spring MVC file upload example for single and multiple files.
Following is the list of tools used for the Spring MVC file upload example.
- Spring 5.0.8 Release (Spring core, spring web, spring webmvc).
- Java 10
- commons-fileupload 1.3.3 (If using Apache Commons file upload)
- Tomcat server V 9.0.10
- Eclipse Photon 4.8.0 for Java EE development
Multipart support in Spring
Spring framework provides an interface MultipartResolver residing in org.springframework.web.multipart package for parsing multipart requests including file uploads.
Spring framework provides support for two implementations of MultipartResolver-
- Implementation based on Apache Commons FileUpload
- Implementation based on Servlet 3.0 support for multipart request parsing.
In this post we’ll see Spring file upload example using both of these implementations and with both Spring XML configuration and Java configuration.
Project structure
- Please refer Spring Web MVC Example With Annotations for getting the project structure using Spring XML configuration.
- Please refer Spring Web MVC Java Configuration Example for getting the project structure using Spring Java configuration.
Spring file upload (multipart request) using Servlet 3.0 support
In my opinion using Servlet 3.0 support for file upload is the better option as you don’t need any additional dependencies to use it, existing servlet container (if it supports servlet 3.0 or higher) will suffice.
Required XML Configuration
To use Servlet 3.0 multipart support you need to add a bean of type StandardServletMultipartResolver in your DispatcherServlet configuration.
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"></bean>
StandardServletMultipartResolver bean has no properties to set, if you want to set some constraints on your file upload like maximum file upload size or temporary location then you need to add a "<multipart-config>" section in web.xml
<servlet> <servlet-name>mvcexample</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> <multipart-config> <!-- 2 MB max file upload size --> <max-file-size>2097152</max-file-size> </multipart-config> </servlet>
Required Java Configuration
If you prefer Spring Java config rather than XML configuration then you need to declare StandardServletMultipartResolver as a bean and need to set a MultipartConfigElement on the Servlet registration for setting configurations like maximum size or storage location.
For Spring MVC with Java config generally AbstractAnnotationConfigDispatcherServletInitializer is used to register DispatcherServlet and it is done automatically. In that case customizeRegistration() method is used to set a MultipartConfigElement on the Servlet registration.
Here is the full class-
import javax.servlet.MultipartConfigElement; import javax.servlet.ServletRegistration; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class SpringMVCConfigInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { // TODO Auto-generated method stub return null; } @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[] {WebConfig.class}; } @Override protected String[] getServletMappings() { return new String[] {"/"}; } @Override protected void customizeRegistration(ServletRegistration.Dynamic registration) { registration.setMultipartConfig(new MultipartConfigElement("", 2097152, 4193304, 2097152)); } }Here note the method customizeRegistration which uses instance of MultipartConfigElement, description of which is as follows.
public MultipartConfigElement(String location, long maxFileSize, long maxRequestSize, int fileSizeThreshold)
- location- the directory location where files will be stored.
- maxFileSize- the maximum size allowed for uploaded files.
- maxRequestSize- the maximum size allowed formultipart/form-data requests.
- fileSizeThreshold- the size threshold after which files will be written to disk.
Declaring StandardServletMultipartResolver as a bean – Java config
@Configuration @EnableWebMvc @ComponentScan(basePackages="org.netjs.controller") public class WebConfig implements WebMvcConfigurer { @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/jsp/"); resolver.setSuffix(".jsp"); return resolver; } public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Bean public MultipartResolver multipartResolver() { return new StandardServletMultipartResolver(); } }
Spring file upload (multipart request) using Commons FileUpload
Another option for parsing multipart request in Spring framework is using Commons FileUpload.
Maven dependency
To use Commons FileUpload you need to have commons-fileupload as a dependency on your classpath. If you are using Maven that can be added in pom.xml as follows-<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency>That adds the following jars-
commons-fileupload-1.3.3.jar commons-io-2.2.jar
Required Spring XML Configuration
To use Apache Commons FileUpload for multipart support you need to configure a bean of type CommonsMultipartResolver with the name multipartResolver in your DispatcherServlet configuration.
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="2097152" /> </bean>
CommonsMultipartResolver provides "maxUploadSize", "maxInMemorySize" and "defaultEncoding" settings as bean properties itself so need to add properties in web.xml as in the case with StandardServletMultipartResolver.
Required Java Configuration
If you prefer Spring Java config then you can configure CommonsMultipartResolver as bean in the following way.
@Bean public MultipartResolver multipartResolver() throws IOException { CommonsMultipartResolver cmr = new CommonsMultipartResolver(); cmr.setMaxUploadSize(2097152); return cmr; }
Views
JSP that is used for uploading a single file.
uploadFile.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html> <html> <head> <meta charset="ISO-8859-1"> <title>Insert title here</title> </head> <body> <form action="uploadFile" method="post" enctype="multipart/form-data"> <table> <tr> <td> <label>Select a file to upload:</label> <input type="file" name="file"> </td> </tr> <tr> <td><input type="submit" value="Upload File"></td> </tr> </table> </form> </body> </html>
In the JSP, enctype="multipart/form-data" attribute is used with the form tag to specify that it is a multipart request.
JSP that is used for uploading multiple files.
uploadMultipleFiles.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html> <html> <head> <meta charset="ISO-8859-1"> <title>Spring File Upload</title> </head> <body> <form action="uploadMultiFile" method="POST" enctype="multipart/form-data"> <table> <tr> <td> <label>Select a file to upload:</label> <input type="file" name="files"> </td> </tr> <tr> <td> <label>Select a file to upload:</label> <input type="file" name="files"> </td> </tr> <tr> <td> <label>Select a file to upload:</label> <input type="file" name="files"> </td> </tr> <tr> <td><input type="submit" value="Upload"></td> </tr> </table> </form> </body> </html>
Here note that the same name “files” is used in all the input fields. That is required so that request is sent as an array of files.
Another JSP shows the upload status by showing a message set in the controller for success or failure of the upload. Also shows some metadata about the uploaded file like name, size and content type.
uploadStatus.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html> <html> <head> <meta charset="ISO-8859-1"> <title>Insert title here</title> </head> <body> <table> <tr> <td>Upload status: ${message}</td> </tr> <tr> <td>File Name: ${file.getOriginalFilename()}</td> </tr> <tr> <td>File Size: ${file.getSize()}</td> </tr> <tr> <td>File Type: ${file.getContentType()}</td> </tr> </table> </body> </html>
Controller class
import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PostMapping; 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.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; @Controller public class FileUploadController { @RequestMapping(value = "/uploadMulti", method = RequestMethod.GET) public String startMultiUpload(Model model) { return "uploadMultipleFiles"; } @RequestMapping(value = "/upload", method = RequestMethod.GET) public String startUpload(Model model) { return "uploadFile"; } // Handler Method for file upload @RequestMapping(value = "/uploadFile", method = RequestMethod.POST) public String uploadFile(@RequestParam("file") MultipartFile file, Model model) { String msg= ""; if(!file.isEmpty()) { BufferedOutputStream bos =null; try { byte[] fileBytes = file.getBytes(); // location to save the file String fileName = "G:\\Test\\"+file.getOriginalFilename(); bos = new BufferedOutputStream(new FileOutputStream(new File(fileName))); bos.write(fileBytes); msg = "Upload successful for " + file.getName(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { if(bos != null) { try { bos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }else { msg = "Upload failed for " + file.getName() + " as file is empty"; } model.addAttribute("message", msg); model.addAttribute("file", file); return "uploadStatus"; } // Handler Method for multiple file uploads @PostMapping(value = "/uploadMultiFile") @ResponseBody public String uploadMultipleFiles(@RequestParam("files") MultipartFile[] files, Model model) { String msg= ""; int emptyCount = 0; for(MultipartFile file : files) { if(!file.isEmpty()) { BufferedOutputStream bos =null; try { byte[] fileBytes = file.getBytes(); // location to save the file String fileName = "G:\\Test\\"+file.getOriginalFilename(); bos = new BufferedOutputStream(new FileOutputStream(new File(fileName))); bos.write(fileBytes); msg = msg + "Upload successful for " + file.getOriginalFilename() + "<br />"; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { if(bos != null) { try { bos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }else { emptyCount++; } } // Equal means no file is selected for upload if(files.length == emptyCount) { msg = "Upload failed as no file is selected"; } return msg; } }
In the controller class, uploadFile() method is used for handling single file upload request which has a parameter of type MultipartFile. In the logic for saving the uploaded file at a location, file path is hardcoded, you may change it to get the path from a property file or with respect to server path.
uploadMultipleFiles() method is used for handling multiple file uploads in the Spring Controller class. In the method note that MultipartFile[] parameter is an array now for holding multiple files. Method uses the new Annotation @PostMapping (from Spring 4.3) which is the shortcut for @RequestMapping(method = RequestMethod.POST).
Also uses the annotation @ResponseBody that indicates a method return value should be bound to the web response body. That way string can be returned as a response not as a logical view name to be resolved to JSP.
MultipartFile has a transferTo() method that can also be used for storing the uploaded file at the given location.
// Handler Method for file upload @RequestMapping(value = "/uploadFile", method = RequestMethod.POST) public String uploadFile(@RequestParam("file") MultipartFile file, Model model) { String msg= ""; if(!file.isEmpty()) { try { String fileName = "G:\\Test\\"+file.getOriginalFilename(); // for storing uploaded file file.transferTo(new File(fileName)); msg = "Upload successful for " + file.getName(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else { msg = "Upload failed for " + file.getName() + " as file is empty"; } model.addAttribute("message", msg); model.addAttribute("file", file); return "uploadStatus"; }
Screens for Spring MVC file upload exmaple
Upload page with one PDF file selected for uploading.
Showing the status of the upload.
If upload is not successful.
Upload page for multiple uploads with two files selected for uploading.
Showing the status of the upload.
That's all for this topic Spring MVC File Upload (Multipart Request) Example. If you have any doubt or any suggestions to make please drop a comment. Thanks!
>>>Return to Spring Tutorial Page
Related Topics
You may also like-
No comments:
Post a Comment