Posts Tagged Multipart

Spring Multifile Uploading Bug: Fixed

Well, they beat me to it; the Spring Multipart Issue has been fixed as of Spring 3.0-RC1. I am happy to see that though a little bummed because I was looking forward to fixing it and submitting a patch. Nice work, to whoever fixed it!

I wrote a general posting about how to do file uploads with the new spring annotations (see Spring Multipart Support With Annotations) so now, with the new multi-file support you can have more than one input file with the same form input name.

The input form becomes

1
2
3
4
5
<form action="upload.do" method="post" enctype="multipart/form-data">
    <div>File 1: <input type="file" name="files" /></div>
    <div>File 2: <input type="file" name="files" /></div>
    <input type="submit" />
</form>

to provide two files with the same form field name.

The controller code does not really change much, other than the fact that the multi-file support does not seem to extend to the @RequestParam() annotation support by default, so I had to use a different method signature.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Controller
@RequestMapping("/upload.do")
public class MultifileUpload {

    @RequestMapping(method=RequestMethod.POST)
    public ModelAndView upload(final MultipartHttpServletRequest request){
        final ModelAndView mav = new ModelAndView("done");

        final List<MultipartFile> multipartFiles = request.getFiles("files");

        // do stuff with the file
        System.out.println("found " + multipartFiles.size() + " files");

        return mav;
    }
}

It’s nice to see that this bug got fixed, and they seem to have dropped the provided support for other upload APIs, though you could still write your own implementation as needed.

Popularity: 14% [?]

  • Share/Bookmark

Tags: , ,

Spring Multipart Support With Annotations

In working on the multi-file upload support in Spring (see Spring Multipart Issue), I had to code up a simple example of how it works now. It took me a little searching to figure out how to use multipart support with the new controller annotation configurations, though it turns out to be really easy. I figured I’d post a quick summary of how it’s done.

With your standard file upload form:

1
2
3
4
<form action="upload.do" method="post" enctype="multipart/form-data">
    <div>File 1: <input type="file" name="file" /></div>
    <input type="submit" />
</form>

posting to your uploading controller, which is defined as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Controller
@RequestMapping("/upload.do")
public class UploadController {

    @SuppressWarnings("unchecked")
    @RequestMapping(method=RequestMethod.POST)
    public ModelAndView upload(@RequestParam("file") final MultipartFile multipartFile){
        final ModelAndView mav = new ModelAndView("done");

        // do stuff with the file

        return mav;
    }
}

which just seems way too simple. Don’t forget to configure the MultipartResolver along with the rest of your spring-mvc config:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<context:annotation-config />
<context:component-scan base-package="com.stehno.springmulti" />

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>
   
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="100000"/><!-- Max size in bytes. -->
</bean>

and that’s it.

Like I said, nothing real exciting here, really just a quick setup starting point.

Note: my fix of the multiple-file upload support is on hold until Spring 3.0 is officially released. I know what needs to be done, it’s just a waiting game now. :-)

Popularity: 88% [?]

  • Share/Bookmark

Tags: , , ,

Spring Multipart Issue

I have been implementing some file upload handlers for s Spring MVC-based application I am working on (at work) and I ran into a frustrating issue with Spring’s nicely integrated MultipartResolver API. It doesn’t support multiple file entries with the same input field name. So, as in my case, if you have a dynamic list of files being imported each having the same HTML input name (not something I can easily change at this point), the resolver will throw an exception about multiple files with the same field name.

In version 2.0.x it simply took the last one of the group and silently went about its business (see CommonsFileUploadSupport.java).

1
2
3
4
5
6
7
8
// multipart file field
CommonsMultipartFile file = new CommonsMultipartFile(fileItem);
multipartFiles.put(file.getName(), file);
if (logger.isDebugEnabled()) {
    logger.debug("Found multipart file [" + file.getName() + "] of size " + file.getSize() +
        " bytes with original filename [" + file.getOriginalFilename() + "], stored " +
        file.getStorageDescription());
}

The “same” code in the 2.5 line throws an exception, which is better at least technically, due to the fact that it tells you about the problem.

1
2
3
4
5
6
7
8
9
10
// multipart file field
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");
}
if (logger.isDebugEnabled()) {
    logger.debug("Found multipart file [" + file.getName() + "] of size " + file.getSize() +
        " bytes with original filename [" + file.getOriginalFilename() + "], stored " +
        file.getStorageDescription());
}

Originally I thought, “cool, I found a Spring bug that I can fix and submit”… then I saw the new code (2.5.x) and realized that this was intentional. I did some searching through the bug tickets and did find one related to this issue Support MultipartFile-array Property. It was then that I found the root of my frustration.

It seems that COS doesn’t support file parts with the same name, thus the feature cannot be implemented there.

I cannot say whether or not COS has a production-ready implementation of a multipart handler, but Jason Hunter is a smart guy so it is at the very least decent; however, it seems short-sighted for the Spring developers to limit the capabilities of file uploading based on the limitations of an API that has not been updated since 2002. Honestly, after looking deeper into the COS source and docs, I am not sure that it will not handle multiple inputs correctly. It looks like the MultipartRequest might not, but the MultipartParser seems pretty raw such that it might be easy to implement a work-around.

In either case, I will have to write or re-write some Spring code to implement another MultipartResolver that will handle multiple input files. It can be done in less than 10 lines of added code if I cut and paste the relevant Spring sources… there are a couple layers of inheritance to deal with and the code that needs to change is in the top parent class. D’oh. (backseat coding, but this probably would have been a good place for a strategy pattern). I do not advocate the cut and paste approach for anything other than absolute necessity (which has only happened one other time for me in the past four years).

The RFC-1867, remains silent on this matter.

Oh, well, when I have a few spare minutes I will setup a test of the COS MultipartParser and see what it can handle. This still may be a fixable Spring bug yet. I will post results.

All in all, if this is the first and only gripe I have about Spring after using it for about four years… that’s not too bad at all. Also, I must say that their source code is very pleasant to browse through.

Popularity: 23% [?]

  • Share/Bookmark

Tags: , , ,

Switch to our mobile site