File upload using Spring MVC and annotation configuration

Spring MVC does special care to upload file to server. It makes file upload an easy work for web application developers. Spring MVC library jar provides CommonsMultipartResolver class that makes special care to form submitted using “multipart/form-data” encode type. We can also specify max file size in this resolver.

Tools Used:

  • Spring MVC 3.0.3
  • Eclipse Indigo 3.7
  • Tomcat 6
  • Jdk 1.6
  • Apache Common File Upload 1.2.0
  • Apache Common IO 2.0.1

As you can see, we need two more jar files to upload file to server using Spring MVC. The name of the jar files are :

  • commons-io-2.0.1.jar
  • commons-fileupload-1.2.1.jar

Step1: Registering CommonsMultipartResolver in Spring MVC Configuration file

We must first register CommonsMultipartResolver class in Spring MVC configuration file so that Spring can handle multipart form data.


<!-- Configure the multipart resolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- one of the properties available; the maximum file size in bytes -->
    <property name="maxUploadSize" value="100000"/>
</bean>

The property “maxUploadSize” can be used to specify the max size of the file that can be uploaded to server. If we try to upload a file that is greater that the size specified in the property then Spring will through MaxUploadSizeExceededException. Later we will also learn how to handle this exception to show user friendly message when file is larger.

Step2: Creating file upload form


package com.raistudies.domain;

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

public class UploadForm {

    private String name = null;
    private CommonsMultipartFile file = null;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public CommonsMultipartFile getFile() {
        return file;
    }
    public void setFile(CommonsMultipartFile file) {
        this.file = file;
        this.name = file.getOriginalFilename();
    }
}

The file upload form contains two property one is name of type String, will contain name of the file to be upload, and the other is the file of type CommonsMultipartFile, will contain file itself. CommonsMultipartFile class is present in Apache Common Fileupload library and Spring MVC converts the form file to the instance of CommonsMultipartFile.

As our form will only contain file element, so we set the name of the file in the setter method of file attribute.

Step3: Creating controller class for file upload


package com.raistudies.controllers;

//imports has been removed to make the code short. You can get full file by downloading it from bellow.

@Controller
@RequestMapping(value="/FileUploadForm.htm")
public class UploadFormController implements HandlerExceptionResolver{

    @RequestMapping(method=RequestMethod.GET)
    public String showForm(ModelMap model){
        UploadForm form = new UploadForm();
        model.addAttribute("FORM", form);
        return "FileUploadForm";
    }

    @RequestMapping(method=RequestMethod.POST)
    public String processForm(@ModelAttribute(value="FORM") UploadForm form,BindingResult result){
        if(!result.hasErrors()){
            FileOutputStream outputStream = null;
            String filePath = System.getProperty("java.io.tmpdir") + "/" + form.getFile().getOriginalFilename();
            try {
                outputStream = new FileOutputStream(new File(filePath));
                outputStream.write(form.getFile().getFileItem().get());
                outputStream.close();
            } catch (Exception e) {
                System.out.println("Error while saving file");
                return "FileUploadForm";
            }
            return "success";
        }else{
            return "FileUploadForm";
        }
    }

    @Override
    public ModelAndView resolveException(HttpServletRequest arg0,
    HttpServletResponse arg1, Object arg2, Exception exception) {
        Map<Object, Object> model = new HashMap<Object, Object>();
        if (exception instanceof MaxUploadSizeExceededException){
            model.put("errors", "File size should be less then "+
            ((MaxUploadSizeExceededException)exception).getMaxUploadSize()+" byte.");
        } else{
            model.put("errors", "Unexpected error: " + exception.getMessage());
        }
        model.put("FORM", new UploadForm());
        return new ModelAndView("/FileUploadForm", (Map) model);
    }
}

The UploadFormController adds the form bean on get method request and save the file included in the request form in temp directory of server in post method.

You can notice one more thing here i.e. the UploadFormController class also implements an interface HandlerExceptionResolver. It is necessary to implement this interface to handle the MaxUploadSizeExceededException that is thrown when form file is larger then the specified max file size. resolveException method shows form with error message in form while dealing with larger file size.

Step4: Creating jsp file for file upload


<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ page session="true" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>File Upload with Spring 3 MVC</title>
        <meta http-equiv="Content-Type" content="text/html; charset=windows-1251" >
    </head>
    <body>
        <h1>File Upload Form</h1><br />
        <form:form commandName="FORM" enctype="multipart/form-data" method="POST">
        <table>
         <tr><td colspan="2" style="color: red;"><form:errors path="*" cssStyle="color : red;"/>
         ${errors}
         </td></tr>
         <tr><td>Name : </td><td><form:input type="file" path="file" /></td></tr>
         <tr><td colspan="2"><input type="submit" value="Upload File" /></td></tr>
        </table>
        </form:form>
    </body>
</html>

The jsp file contains a form with file input. The enctype of the form must be “multipart/form-data” to send binary data like file to server.

That is all. You can deploy the war file in Tomcat 6 and hit the url in browser, you will get following form:

File Upload Form using Spring MVC

File Upload Form using Spring MVC

Select a very large file (more than 100KB) and click on “Upload File” button. You will get following error :

File Size Error in Upload Form Spring MVC

File Size Error in Upload Form Spring MVC

Now, select a file less than 100 kb and click on “Upload File” button. You will be forwarded to success page which will show you the name of the file uploaded.

File Upload Successful Page

File Upload Successful Page

You can download the source and war file of the example from following links:

Source: Download

War: Download

Related Posts:

Leave a comment ?

11 Comments.

  1. Thanks mate!

  2. Simple nice implementation, specially that you have used Streaming instead of Byte Array which causes memory issues with big uploads.

  3. Thanks for the sample code! The only issue I have been unable to resolve is stopping the upload with MaxUploadSizeExceededException. The error does get displayed to the user but only after the entire file has been uploaded. Any way to resolve that?

  4. Hi ,

    Thanks for the tutorial.Can you plz tell me how to use uploadTempDir property? I had set the value in the dispatcher servlet but somehow it is not recognized by the controller class.Im not getting the prob :(

    Thanks
    Gayatri

  5. This is the configuration in the dispatcher servlet file

  6. Hi
    I have problems running the example, the bean that the controller receives is empty. I’ve inserted some system.out in the code and this is the result:
    public String showForm(ModelMap model){
    UploadForm form = new UploadForm();
    model.addAttribute(“FORM”, form);
    System.out.println(“showForm: ” + form.toString() );
    System.out.println(“showForm 2 ” + form.getFile() );
    return “FileUploadForm”;
    )

    in the console out i have :
    showForm: UploadForm@1e9d0cc
    showForm 2 null

    @RequestMapping(method=RequestMethod.POST)
    public String processForm(@ModelAttribute(value=”FORM”) UploadForm form,BindingResult result){
    System.out.println(“In processForm ” + form.toString() );
    if( !result.hasErrors() ){
    System.out.println(“In processForm 1 ” + form.getFile()); ……

    in the console out i have :
    In processForm UploadForm@185e155
    In processForm 1 null

    so the file is null, i cannot figure out the problem, I thought it could be a session problem because the two UploadForm istances are different as the numbers suggest, but i’m not sure about that.
    COuld someone give me some suggestion?
    thanks
    Paolo

    • Hi

      Inspecting the request with firebug I can see
      that the body coontains only the boundary seprarator:
      —————————–43132435531185–
      and the content-lenght is 47 byte, so the browser doesnt send the content. Any error in in the form?

      Name :

    • As you have not defined the UploadForm attribute as SessionAttribute, it will create the object of UploadForm for every request. That is not a problem. Just check the html form attribute names withe form attribute names.

  7. Hi
    I’ve figured out the problem.

    I am using a XML-less configuration and the problem was the method name to create the bean of type CommonsMultipartResolver , i’ve used configureMultipartResolver instead of multipartResolver as method name. I was fooled from the system.out that i could see in the log so i though the injection was working,but probably it created a bean with a wrong name.
    So when I put the followong piece of code in my WebConfig class it worked.

    @Bean
    public CommonsMultipartResolver multipartResolver() {
    System.out.println(“–>>>>configureMultipartResolver<<<<>>>>>>DONEEE<<<<<<<<——–");
    return multipartResolver;
    }

  8. where the uploaded file saved

Leave a Comment Cancel reply


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>