Q:

Spring 3.0 FileUpload only with POST?

I am trying to upload a File with one parameter using spring 3.
This is my controller method which should enable this service:
@RequestMapping(value="/{id}", method = RequestMethod.PUT, headers="content-type=multipart/form-data")
public ResponseEntity<String> uploadImageWithJsonParamater(@PathVariable("id") Long id, @RequestParam String json, @RequestParam MultipartFile customerSignFile) {
    //...
}

The problem is, that the server cannot dispatch to this method:
MissingServletRequestParameterException: Required String parameter 'json' is not present
If I change the RequestMethod from PUT to POST, everything  is fine. So does anybody know the problem?
It seems that it isn't allowed to transmit form-data via PUT.
I debugged a little bit and the following method returns false in the PUT case but true in the POST case:
public boolean isMultipart(HttpServletRequest request) {
    return (request != null && ServletFileUpload.isMultipartContent(request));
}

I would appreciate any help!
Thanks in advance!

A:

You can accomplish this using spring's HiddenHttpMethodFilter, but you will need to ensure that you put a Spring MultipartFilter before the HiddenHttpMethodFilter in your web.xml filter chain.
For example: In your web.xml
<filter>
    <filter-name>MultipartFilter</filter-name>
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
    <init-param>
        <param-name>multipartResolverBeanName</param-name>
        <param-value>filterMultipartResolver</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>MultipartFilter</filter-name>
    <servlet-name>/*</servlet-name>
</filter-mapping>
<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <servlet-name>/*</servlet-name>
</filter-mapping>

Then in your spring-config.xml add a reference to CommonsMultipartResolver:
<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

Note that, if you don't add the spring-config.xml entry your MultipartFilter will default to   using a MultipartResolver that uses servlet spec 3.0 implementation and will throw error like: NoSuchMethodError HttpServletRequest.getParts() if you're not using 3.0.

A:

I run into the same problem.
My solution was implementing an ExtendedMultipartResolver which accept multiparts sent via http method PUT as well.
Just copy the CommonsMultipartResolver code, rename the class and change the implementation of the isMultipart() function to your needs:
private boolean isMultipartContent(HttpServletRequest request) {
  String httpMethod = request.getMethod().toLowerCase();
  // test for allowed methods here...
  String contentType = request.getContentType();
  return (contentType != null && contentType.toLowerCase().startsWith("multipart"));
}

public boolean isMultipart(HttpServletRequest request) {
      return (request != null && isMultipartContent(request));
}

You could check for POST, PUT or other HTTP methods here. In my case, all methods will be accepted, 
as my controller annotations will filter to the allowed methods.
Dont forget to configure the bean in the spring web context:
<bean id="multipartResolver" class="sample.package.ExtendedMultipartResolver"/>

hope that helps.
cheers
chris

A:

You can't send form data via PUT as per the HTML standard. You can only send files via PUT, and in this case they're send more efficiently then with POST (because you no longer have all the multi-part overhead), but in order for you PUT listening server side component to actually receive a file via PUT you have to make sure that you actually send a PUT command to it (via javascript for instance). Here's an example that uses JQuery:
$('#file_upload').fileUpload({
    namespace: 'file_upload',
    url: '/path',
    method: 'PUT'
});

