Interview Questions

Spring File Upload

In this article we will discuss about uploading files using Spring MVC applications.

In application projects, we may often be faced with requirements to upload files from UI to the web server. This can be done in spring using org.springframework.web.multipart.commons.CommonsMultipartResolver bean.

The CommonsMultipartResolver is a servlet based implementation of Jakarta Commons File Upload api. It has properties to specify maxUploadSize, maxInMemorySize and DefaultEncoding for the file to be uploaded.

Let see a simple example of uploading a file containing user details from UI.

Here is the UserInfo.jsp file

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://java.sun.com/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>Home Page</title>
    </head>

<body>
    Today is ${date}
<br>
<br>
    Please provide user details
<br>

<form:form method="POST" commandName="user"
        enctype="multipart/form-data">
        <table>
                <tr>
                        <td>User Name :</td>
                        <td><form:input path="userName"></form:input></td>
                </tr>
                <tr>
                        <td>Age :</td>
                        <td><form:input path="age" /></td>
                </tr>

                <tr>
                        <td>Upload User Details :</td>
                        <td colspan="2"><spring:bind path="user.userDetails">
                                <input type="file" name="file" />
                        </spring:bind>
                        </td>
                </tr>

                <tr>
                        <td colspan="2"><input type="submit" name="submit"
                                value="submit">
                        </td>
                </tr>
        </table>
</form:form>
</body>
</html>

Have a look at the corresponding bean file for the user form.

package in.techdive.spring;

import java.io.Serializable;

public class User implements Serializable
{

    private static final long serialVersionUID = -7320233902190166054L;

    public User()
    {
    }

    private String userName;
    private int    age;
    private byte[] userDetails;

    public String getUserName()
    {
        return userName;
    }

    public void setUserName(String userName)
    {
        this.userName = userName;
    }

    public int getAge()
    {
        return age;
    }

    public void setAge(int age)
    {
        this.age = age;
    }

    public byte[] getUserDetails()
    {
        return userDetails;
    }

    public void setUserDetails(byte[] userDetails)
    {
        this.userDetails = userDetails;
    }
}

Note that the property userDetails of type byte[] is used in the jsp to get the file contents as bytes.

Take a look at the spring configuration file. It consist of the CommonsMultiPartResolver bean and other Controller beans.

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix">
        <value>/WEB-INF/jsp/</value>
    </property>

   <property name="suffix">
        <value>.jsp</value>
   </property>
</bean>

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<!-- URL and Corresponding Controller mapping to come here -->
        <property name="urlMap">
                <map>
                    <entry key="/" value-ref="simpleSpringController" />
                    <entry key="/userInfo.htm" value-ref="simpleSpringController" />
                </map>
        </property>
</bean>

<bean id="simpleSpringController" class="com.techdive.spring.SimpleSpringController">
        <property name="formView" value="userInfo" />
        <property name="successView" value="welcome" />
</bean>

Consider the SimpleSpringController.java, it gets the user details along with the upload file in the HttpRequest.
It is then casted in to MultipartHttpServletRequest and then using getFile() method, we get the CommonsMultiPartFile.
Then the file is written to the outputStream to a new file in the given location.

/**
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.ui.ModelMap;
import org.springframework.validation.BindException;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

public class SimpleSpringController extends SimpleFormController
{

    private ModelMap modelMap = new ModelMap();

    public SimpleSpringController()
    {
        setCommandClass(User.class);
        setCommandName("user");
    }

    protected ModelAndView onSubmit(HttpServletRequest request,
            HttpServletResponse response, Object command, BindException errors)
            throws Exception
    {
        User user = (User) command;
        ModelAndView mv = new ModelAndView(getSuccessView(), "user", user);
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;

        CommonsMultipartFile file = (CommonsMultipartFile) multipartRequest
                .getFile("file");

        Map fileMap = multipartRequest.getFileMap();

        Set<String> keys = fileMap.keySet();

        for (String s : keys)
        {
            System.out.println(s);
        }
        System.out.println("File data...." + user.getPhoto());

        InputStream sourceStream = null;
        OutputStream destStream = null;

        try
        {
            sourceStream = file.getInputStream();
            destStream = new BufferedOutputStream(new FileOutputStream(
                    "C:\\photo"));
            int bytesRead = 0;
            byte[] buffer = new byte[8192];

            while ((bytesRead = sourceStream.read(buffer, 0, 8192)) != -1)
            {
                System.out.println(new String(buffer));
                destStream.write(buffer, 0, bytesRead);
            }

            try
            {
                if (sourceStream != null)
                {
                    sourceStream.close();
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }

            try
            {
                if (destStream != null)
                {
                    destStream.flush();
                    destStream.close();
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return mv;
    }

    protected Map referenceData(HttpServletRequest request) throws Exception
    {
        modelMap.put("date", new Date());
        return modelMap;
    }
}

In this way, files can be uploaded from UI in Spring MVC applications.

Note: you need to include the following additional jar files
1. commons-fileupload.jar
2. commons-io.jar