Maximum Zeal ~ Emphatic prose on indulged fascinations

Implementing single and multiple file multipart uploads using Spring 2.5

Overview

This article has two objectives. Firstly it aims to compare and contrast the means necessary to enable single file uploads as opposed to multiple file multipart uploads. And, secondly, it shows that multiple file uploads cannot be implemented in exactly the same way as single file uploads (when using Spring 2.5) and then proceeds to outline a number of alternative solutions. The article covers only Commons Fileupload support as that is not only the only library now supported in Spring 2.5 but also it is a very good api.

Example code from a complete example project will be used in the article and the example project is made available as a compressed file at the end. It can be used as a skeletal implementation and as a test harness. There’s nothing revolutionary or difficult here but hopefully this will serve as an informative and more complete resource that I wish I had when I was trying to implement multiple file uploads using Spring.

Table of contents

  • Introduction
  • Single file upload
    • Create an html form to test uploads
    • Create a form backing object bean
    • Create a file upload controller
    • Define Spring configuration
  • Multiple file upload
    • Solution 1 – Modify form backing object to accept multiple files
    • Solution 2 – Use the raw http servlet request
    • Solution 3 – Disable Spring support and use commons fileupload directly
    • Solution 4 – Using a cross cut to disable spring support conditionally
  • Conclusion
  • Example project
  • Related Spring Jira Issues

The reader is encouraged to have a look at the open Spring jira issues related to this article and add his/her vote to those issues.

Introduction

A file upload can be processed either as a byte array, a multipart file or as a string. Here, for brevity and simplicity, only the multipart file option is explored and used as an example. For details of the other two please refer to the download of the example project.

Single file upload

A single file upload, in Spring 2.5, is implemented in a few simple steps.

  1. Create a file upload form to test uploads.
  2. Create a form backing object.
  3. Create a file upload controller.
  4. Define Spring configuration.

Let’s go through these in turn using small examples.

Create an html form to test uploads
<form method="post" action="/spring-multi-file-upload/upload/multiPartFileSingle" enctype="multipart/form-data">
<p>Type: <input type="text" name="type" value="multiPartFileSingle" size="60" /></p>
<p>File: <input type="file" name="file" size="60" /></p>
<p><input type="submit" value="Upload" /></p>
</form>
Create a form backing object bean
package single.upload.beans;

import org.springframework.web.multipart.MultipartFile;

public class MultiPartFileUploadBean {
    
    private String        type;
    
    private MultipartFile file;
    
    public String getType() {
        return type;
    }
    
    public void setType(String type) {
        this.type = type;
    }
    
    public void setFile(MultipartFile file) {
        this.file = file;
    }
    
    public MultipartFile getFile() {
        return file;
    }
    
}

At runtime when a multi part http request is received Spring parses the request and automatically binds all form input values to this form backing object bean. Any binding errors are supplied to you as an argument to your controller.

Create a file upload controller.
package single.upload.controllers;

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

import org.springframework.util.Assert;
import org.springframework.validation.BindException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import single.upload.beans.MultiPartFileUploadBean;

public class MultiPartFileUploadController extends SimpleFormController {
    
    protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command,
            BindException errors) throws Exception {
        
        /*
         * validate type of request and type of form backing object bean
         */
        Assert.state(request instanceof MultipartHttpServletRequest, "request !instanceof MultipartHttpServletRequest");
        Assert.state(command instanceof MultiPartFileUploadBean, "command !instanceof MultiPartFileUploadBean");
        
        /*
         * validate binding of text input field
         */
        MultiPartFileUploadBean bean = (MultiPartFileUploadBean) command;
        Assert.state(bean.getType().equals("multiPartFileSingle"), "type != multiPartFileSingle");
        
        /*
         * validate binding of uploaded file
         */
        MultipartFile file = bean.getFile();
        Assert.notNull(file, "multi part file must not be null");
        
        return super.onSubmit(request, response, command, errors);
    }
    
}
Define Spring configuration.
Enable multipart resolver support.
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="maxUploadSize" value="5000000" />
	<property name="maxInMemorySize" value="5000000" />
</bean>

There are a few points to note here.

  • In Spring 2.5 the CommonsMultipartResolver class is now the only remaining implementation of the MultipartResolver interface.
  • The bean id for this bean absolutely must be called ‘multipartResolver’. Otherwise your controller will get an instance of RequestFacade instead of MultipartHttpServletRequest.
  • All properties for this bean are optional.
  • This bean must be defined in the dispatcher servlet application context.
Define remaining Spring beans.
<bean id="local.MultiPartFileUploadControllerSingle" class="single.upload.controllers.MultiPartFileUploadController">
	<property name="commandClass" value="single.upload.beans.MultiPartFileUploadBean" />
	<property name="formView" value="form" />
	<property name="successView" value="success" />
</bean>

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
	<property name="mappings">
		<value>
			/multiPartFileSingle=local.MultiPartFileUploadControllerSingle
		</value>
	</property>
</bean>

The single file upload implementation is complete and can be tested by deploying and using the example project. Instructions are provided at the end of the article.

Multiple file upload

A number of potential solutions (including one that doesn’t work) are provided here and contrasted with each other.

Solution 1 – Modify form backing object to accept multiple files

NOTE: This solution doesn’t work and is here simply for illustration and discussion purposes.

You may expect that if you modify the single file upload implementation very slightly to work with multiple files it’ll just work. The form backing object bean should now expect an array of multipart files. The controller can be modifying accordingly to accept the new form backing object bean and the HTML file should now upload multiple files.

package multi.upload.beans;

import org.springframework.web.multipart.MultipartFile;

public class MultiPartFileUploadBean {
    
    private String        type;
    
    private MultipartFile[] files;
    
    public String getType() {
        return type;
    }
    
    public void setType(String type) {
        this.type = type;
    }
    
    public void setFiles(MultipartFile[] file) {
        this.files = file;
    }
    
    public MultipartFile[] getFiles() {
        return files;
    }
    
}

This should really work and do so dynamically. The incoming request should be able to define a form input called ‘files’ or ‘files[]‘ that is populated with many files and the form backing object should be populated with all file items. In fact this doesn’t work and the following exception is thrown.

org.springframework.web.multipart.MultipartException: Multiple files for field name [files] found - not supported by MultipartResolver
	org.springframework.web.multipart.commons.CommonsFileUploadSupport.parseFileItems(CommonsFileUploadSupport.java:254)
	org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:166)
	org.springframework.web.multipart.commons.CommonsMultipartResolver.resolveMultipart(CommonsMultipartResolver.java:149)
	org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1015)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:851)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

In fact this is caused by the following code in CommonsFileUploadSupport added in Spring 2.5.

CommonsMultipartFile file = new CommonsMultipartFile(fileItem);
if (multipartFiles.put(file.getName(), file) != null) {
	throw new MultipartException(
			"Multiple files for field name [" + file.getName() + "] found - not supported by MultipartResolver");
}

There is even a two-year old open jira issue with major priority for this problem with an attached patch but regrettably it still remains unassigned. I would strongly suggest that the reader add a vote and comment to that bug and watch it for progress as well so that it can gain some traction. A small mention of it on the spring user mailing list also exists.

So if the above most intuitive way doesn’t work then what are the remaining options? Read on.

Solution 2 – Use the raw request.

This solution involves forgetting everything above and simply using the raw request as follows. Since the binding of the form backing object bean does not work for multiple files that class can be discard altogether and since the controller doesn’t need the command and the binding errors passed as arguments anymore it no longer needs to extend SimpleFormController. In fact it doesn’t need to extend anything at all. As a result the implementation is greatly simplified.

The remaining part of the solution depends on whether the client (in this case the html form) wants to use unique input names such as ‘file1′ and ‘file2′ or the same input name such as ‘files’ for multiple files. If the client is agreeable to using unique parameter names then the solution is easier as below.

HTML Form
<form method="post" action="/spring-multi-file-upload/upload/genericMulti" enctype="multipart/form-data">
<p>Type: <input type="text" name="type" value="genericFileMulti" size="60" /></p>
<p>File1: <input type="file" name="file1" size="60" /></p>
<p>File2: <input type="file" name="file2" size="60" /></p>
<p><input type="submit" value="Upload" /></p>
</form>
Controller
package multi.upload.controllers;

import java.io.File;
import java.util.Map;

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

import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class GenericFileUploadController implements Controller {
    
    @Override
    @SuppressWarnings("unchecked")
    public ModelAndView handleRequest(final HttpServletRequest request, final HttpServletResponse response)
            throws Exception {
        
        /*
         * validate request type
         */
        Assert.state(request instanceof MultipartHttpServletRequest, "request !instanceof MultipartHttpServletRequest");
        final MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
        
        /*
         * validate text input
         */
        Assert.state(request.getParameter("type").equals("genericFileMulti"), "type != genericFileMulti");
        
        /*
         * extract files
         */
        final Map files = multiRequest.getFileMap();
        Assert.state(files.size() > 0, "0 files exist");
        
        /*
         * process files
         */
        for (MultipartFile file : files.values()) {
            file.transferTo(new File(new File("/Users/dhruba/tmp"), file.getOriginalFilename()));
        }
        
        return new ModelAndView("success");
        
    }
    
}
Spring configuration
<bean id="local.GenericFileUploadControllerMulti" class="multi.upload.controllers.GenericFileUploadController" />

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
	<property name="mappings">
		<value>
			/genericMulti=local.GenericFileUploadControllerMulti
		</value>
	</property>
</bean>

If however the client insists on using the same form input name such as ‘files[]‘ or ‘files’ and then populating that name with multiple files then a small hack is necessary as follows. As noted above Spring 2.5 throws an exception if it detects the same form input name of type file more than once. CommonsFileUploadSupport – the class which throws that exception is not final and the method which throws that exception is protected so using the wonders of inheritance and subclassing one can simply fix/modify the logic a little bit as follows. The change I’ve made is literally one word representing one method invocation which enables us to have multiple files incoming under the same form input name.

package resolver;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import org.apache.commons.fileupload.FileItem;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

public class MultiCommonsMultipartResolver extends CommonsMultipartResolver {
    
    public MultiCommonsMultipartResolver() {
    }
    
    public MultiCommonsMultipartResolver(ServletContext servletContext) {
        super(servletContext);
    }
    
    @Override
    @SuppressWarnings("unchecked")
    protected MultipartParsingResult parseFileItems(List fileItems, String encoding) {
        Map multipartFiles = new HashMap();
        Map multipartParameters = new HashMap();
        
        // Extract multipart files and multipart parameters.
        for (Iterator it = fileItems.iterator(); it.hasNext();) {
            FileItem fileItem = (FileItem) it.next();
            if (fileItem.isFormField()) {
                String value = null;
                if (encoding != null) {
                    try {
                        value = fileItem.getString(encoding);
                    } catch (UnsupportedEncodingException ex) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Could not decode multipart item '" + fileItem.getFieldName()
                                    + "' with encoding '" + encoding + "': using platform default");
                        }
                        value = fileItem.getString();
                    }
                } else {
                    value = fileItem.getString();
                }
                String[] curParam = (String[]) multipartParameters.get(fileItem.getFieldName());
                if (curParam == null) {
                    // simple form field
                    multipartParameters.put(fileItem.getFieldName(), new String[] { value });
                } else {
                    // array of simple form fields
                    String[] newParam = StringUtils.addStringToArray(curParam, value);
                    multipartParameters.put(fileItem.getFieldName(), newParam);
                }
            } else {
                // multipart file field
                CommonsMultipartFile file = new CommonsMultipartFile(fileItem);
                if (multipartFiles.put(fileItem.getName(), file) != null) {
                    throw new MultipartException("Multiple files for field name [" + file.getName()
                            + "] found - not supported by MultipartResolver");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Found multipart file [" + file.getName() + "] of size " + file.getSize()
                            + " bytes with original filename [" + file.getOriginalFilename() + "], stored "
                            + file.getStorageDescription());
                }
            }
        }
        return new MultipartParsingResult(multipartFiles, multipartParameters);
    }
    
}

This is identical to the Spring class it extends except for one tiny change which is highlighted in colour (and italics for feed readers) above. This change uses the name of the uploaded file instead of the name of the form input parameter. This has two benefits – one is that now we can have multiple files coming in under the same form input parameter name and the second is that this change ensures that the file names coming in are unique. As this class, by virtue of being a subclass, is identical to the original multipart resolver it can be used in place of the original bean definition as follows.

<bean id="multipartResolver" class="resolver.MultiCommonsMultipartResolver">
	<property name="maxUploadSize" value="5000000" />
	<property name="maxInMemorySize" value="5000000" />
</bean>

Now the client can upload multiple files under the same form input parameter. Although I don’t like such copy and paste kind of work, given how long that jira issue has remained open, I’d rather resort to such quick fixes at my end than wait for fixes at Spring’s end for this particular problem.

Solution 3 – Disable Spring support and use commons fileupload directly.

The final way of achieving multiple file multipart upload is to remove the middle man, Spring, and use what’s underneath the covers directly – commons fileupload (CFU). CFU provides excellent support for any number of file uploads together with other kinds of form inputs and has an excellent object oriented and intuitive api. Its usage is also very well documented so I won’t bother repeating its usage here. However please note the following very important facts about this particular solution to the problem.

  • In order to use CFU the multipartResolver bean absolutely must not exist anywhere in the Spring application context. If you do have the multi part resolver enabled then Spring will intercept the multipart request and process it first and then by the time the request gets to your controller, although it will be a multipart request, CFU will report zero files found. In order for CFU to work correctly it must get the raw request untouched by anything else. This is documented in its first FAQ entry although it doesn’t mention Spring in particular.
  • If you use CFU directly then any other controllers that are loaded in the same Spring application context must be migrated to using the CFU api too. The choice is exclusive per application context – either Spring or CFU. Depending on how many controllers you already have using Spring file upload support this may be a discouraging factor.
  • CFU provides a streaming api which is much leaner and faster than any other way of iterating over and processing files. If your work is performance critical then your only option may be to use CFU directly.
Solution 4 – Using a cross cut to conditionally disable Spring support.

If you have Spring controllers already using the Spring based commons multiresolver support for single or multiple file uploads (either using the form backing object bean for single uploads or using the raw request for multi file uploads) then you have no choice but to use that for all controllers in that particular Spring application context. Commons file upload (CFU) cannot be used directly in any controller while Spring commons multi resolver is enabled as Spring intercepts and processes the request first and, as a result, by the time the request gets to your CFU based controller CFU reports zero files found. This is also stated in CFU’s first FAQ entry.

However as we discussed previously you may want to use CFU directly to remove the extra layer of indirection or to achieve better performance through the use of the CFU streaming api. So how can CFU be used alongside the Spring multi resolver support without migrating all Spring based controllers to the new CFU api? The answer that I came up with is a cross cut which conditionally allows the client to decide if that particular request should be processed by Spring or be allowed to pass through to CFU directly. The code follows.

Multipart resolver disabling aspect

The aspect below proxies the real multipartResolver bean, intercepts one of its methods and modifies its return logic very slightly based on whether a particular client request has requested that behaviour. It essentially flips the boolean return value of CommonsMultipartResolver.isMultipart(HttpServletRequest) from true to false indicating to Spring that it should leave the request object alone which then CFU receives fresh and processes. The client indicates that a particular request should be intercepted by this aspect by posting to a url like /spring-multi-file-upload/upload/genericMulti?_multipartResolverDisable=1. The extra GET parameter is what triggers the aspect’s behaviour. The end result is that by default all multipart requests are processed by Spring but when you want to use CFU directly simply add the GET parameter and your CFU based controller will get an unprocessed and unmodified http servlet request.

package resolver;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartResolver;

/**
 * Disables the spring multipart resolver for specific client requests and
 * therefore keeps the request intact so that controllers can process it in
 * whatever way they wish. This behaviour is triggered by a particular GET
 * parameter in the client request so it is configurable.
 * @author dhruba
 * @see MultipartResolver
 */
@Aspect
public class MultipartResolverDisablingAspect {
    
    /**
     * GET parameter which, if present in request, enables advice.
     */
    private static final String DISABLING_HTTP_REQUEST_PARAMETER_KEY = "_multipartResolverDisable";
    
    private static boolean disablingParameterExists(final HttpServletRequest request) {
        Assert.notNull(request);
        return request.getParameter(DISABLING_HTTP_REQUEST_PARAMETER_KEY) != null;
    }
    
    /**
     * If above GET parameter exists in request then prompt the spring multipart
     * resolver to always tell spring that request is not of type multipart.
     * Spring then does not process the request any further.
     * @param pjp
     * @param request
     * @return
     * @throws Throwable
     */
    @Around("isMultipartOperation() && args(request)")
    public Object disableIsMultipartOperation(final ProceedingJoinPoint pjp, final HttpServletRequest request)
            throws Throwable {
        
        Assert.notNull(pjp);
        Assert.notNull(request);
        
        if (disablingParameterExists(request)) {
            return Boolean.FALSE;
        }
        
        return pjp.proceed();
    }
    
    /**
     * Applies to any implementation of {@linkplain MultipartResolver}
     */
    @SuppressWarnings("unused")
    @Pointcut("execution(public boolean " + "org.springframework.web.multipart.MultipartResolver."
            + "isMultipart(javax.servlet.http.HttpServletRequest))")
    private void isMultipartOperation() {}
    
}
Associated Spring configuration
<aop:aspectj-autoproxy proxy-target-class="false" />

<bean class="resolver.MultipartResolverDisablingAspect" />

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="maxUploadSize" value="5000000" />
	<property name="maxInMemorySize" value="5000000" />
</bean>

Note that the aspect applies to any implementation of the MultipartResolver interface so it’ll work even on your own subclasses of CommonsMultipartResolver.

Conclusion

Spring 2.5 provides excellent support for single file uploads. However the same intuitive and easy-to-use programming model does not extend to multiple file uploads in the way that you would expect. There is a bug filed but it has remained inactive. The alternative solutions are either to use the raw request or to migrate altogether to using CFU directly. To be honest I can’t see any reason to use Spring as a middle man for file uploads when one can use CFU directly. The additional layer of abstraction has a performance overhead, doesn’t provide any great degree of added value for conventional processing and also precludes you from using the CFU streaming api support which is by far the fastest way of iterating over and processing file uploads. However I have presented the options and now the choices are upto you.

Example project

The example project is an Eclipse project and can be downloaded. The structure of the project is as follows.

spring-multi-file-upload
|-- pom.xml
`-- src
    |-- main
    |   |-- java
    |   |   |-- multi
    |   |   |   `-- upload
    |   |   |       |-- beans
    |   |   |       |   |-- ByteArrayFileUploadBean.java
    |   |   |       |   |-- MultiPartFileUploadBean.java
    |   |   |       |   `-- StringFileUploadBean.java
    |   |   |       `-- controllers
    |   |   |           |-- ByteArrayFileUploadController.java
    |   |   |           |-- GenericFileUploadController.java
    |   |   |           |-- MultiPartFileUploadController.java
    |   |   |           |-- ParallelGenericFileUploadController.java
    |   |   |           `-- StringFileUploadController.java
    |   |   |-- resolver
    |   |   |   |-- MultiCommonsMultipartResolver.java
    |   |   |   `-- MultipartResolverDisablingAspect.java
    |   |   `-- single
    |   |       `-- upload
    |   |           |-- beans
    |   |           |   |-- ByteArrayFileUploadBean.java
    |   |           |   |-- MultiPartFileUploadBean.java
    |   |           |   `-- StringFileUploadBean.java
    |   |           `-- controllers
    |   |               |-- ByteArrayFileUploadController.java
    |   |               |-- MultiPartFileUploadController.java
    |   |               `-- StringFileUploadController.java
    |   |-- resources
    |   |   `-- logback.xml
    |   `-- webapp
    |       |-- META-INF
    |       |   `-- MANIFEST.MF
    |       |-- WEB-INF
    |       |   |-- deploy-context.xml
    |       |   |-- jsp
    |       |   |   |-- form.jsp
    |       |   |   `-- success.jsp
    |       |   |-- spring-multi-file-upload-servlet.xml
    |       |   `-- web.xml
    |       |-- index.jsp
    |       `-- tests
    |           |-- aspect.html
    |           |-- generic.html
    |           |-- multiple.html
    |           `-- single.html
    `-- test
        |-- java
        |   `-- app
        |       `-- upload
        |           `-- TestContext.java
        `-- resources

Build a war using maven as follows: mvn clean package and then deploy to tomcat or similar. The test forms can be run from the following urls.

  • http://localhost:8080/spring-multi-file-upload/tests/single.html
  • http://localhost:8080/spring-multi-file-upload/tests/multiple.html
  • http://localhost:8080/spring-multi-file-upload/tests/aspect.html
  • http://localhost:8080/spring-multi-file-upload/tests/generic.html

Then depending on which form you have posted they go to the respective controller which receives that particular url.

Related Spring Jira Issues

Here are the Spring jira issues that are related to this article.

The reader is encouraged to watch and vote for these issues so that they get resolved – particularly the first two issues are most important. The last one is the same as the one before for all intents and purposes.

Update [2009-01-04]: Added ParallelGenericFileUploadController just for fun which uploads multiple files in parallel.

25 Responses to Implementing single and multiple file multipart uploads using Spring 2.5

  1. Just wanted to say thanks for publishing this post! It’s been very helpful in helping me get up-to-speed with using Spring to upload files.

    • I’m using Spring 3 for my current project, but the documentation does not say anything about uploading multiple files. How does it work?

      Chris

      • Chris have a look at this jira. Quoted from there: “The MultipartRequest now has a List getFiles(String) method, as well as a MultiValueMap getMultiFileMap() method”. So the functionality exists but I can’t say whether it is in the most recent Spring milestone or whether you’ll have to work with a snapshot. Thanks for stopping by.

        • The functionality seems not to be in M4, so I’ll have to find another way to do a multifile upload. But thanks for the quick reply ;)

  2. Hi Dhruba,

    I hope it is a very Nice Article.

    I have not gone through your entire article but if you have a solution to the below one then please share.

    Did you face Jvm heap out size of error while uploading the files.
    As per my understanding if you upload a very huge file using Multipart resolver, it first loads the file in to memory and then writes in to the destination location and causes the heap out of memory error.

    Instead it should read the file as a stream and also simultaneously write the file to destination directory.

    What is the size attribute you have mentioned here?
    ———————————————————————————————————————————————

    Type:
    File1:
    File2:

    ———————————————————————————————————————————————–

    Is it necessary to use aop-proxy?

    Thank You,
    Manoj

  3. Hi Manoj. Yes Spring does load the file into memory but also allows you to limit the max upload size. For streaming uploads you can use Commons File Upload. Regarding your other query about the exception I can’t look into this further at the moment as I have no Internet access (currently replying on iPhone). For now I’d suggest looking at the Spring documentation. Thanks for stopping by.

    • Thanks a Lot Dhruba for the reply.

      Think about a situation where in an WebApp multiple users upload files, even if the file size is not that high, it will through an Out of memory exception.

      Yes , CFU could be a solution to this, But do you think it is one of the drawback of the Springs’ multipart resolver as compared to other frameworks like Struts where we used the “FormFile” to stream the file being uploaded.

      Thank You,
      Manoj

  4. Manoj – I am extremely busy at the moment. This blog post is the extent of the help I can give you. Please seek further help at the Spring Framework forums where there will be many other people who can spare the time and have the expertise to help you more directly.

  5. Hey Dhruba, how are you doing? I´m getting a ClassCastException when trying to cas the HttpServletRequest to MultipartHttpServletRequest, do you have any clues on this? :(

  6. I just wanted to say thanks for the blog post – it helped alot. I was attempting to solve the same problem but from webflow.

    Here’s the solution I settled on:

    public String handleMultifileUpload(RequestContext context) {

    ServletExternalContext externalContext = (ServletExternalContext) context.getExternalContext();
    final MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) externalContext.getNativeRequest();
    Map files = multiRequest.getFileMap();

    Logger log = Logger.getLogger(InteractionUploadHandler.class);

    for (MultipartFile file : files.values()) {
    log.error(“entered method processFile”);
    log.error( “file uploaded:” + file.getOriginalFilename());

    }

    return “ok”;
    }

Leave a Reply