4

I am using Spring MVC 4, and I have a controller with the below mapping/method:

@RequestMapping(value = "/me/bio", method = RequestMethod.POST, consumes = { "multipart/form-data" })
@ResponseBody
public JsonResponse<Boolean> saveProfileBio1(Account account, @RequestPart("file") MultipartFile file, @RequestPart("profile") @Valid ProfileBio profileBio) throws ValidationException, IOException {
...//code here
}

When I submit a multipart form data request it fails with HTTP 400 Bad request with the error " org.springframework.web.multipart.support.MissingS ervletRequestPartException: Required request part 'profile' is not present"

Below is the raw request:

------WebKitFormBoundarynU961NKt3K534rCg
Content-Disposition: form-data; name="profile"
{"profileName":"Zack Smith","profileDescription":"xxx","profileWebLink" :"www.abc","profilePictureUrl":"https://s3.amazonaws.com/xxx-images/default.png","profileTitle":"CTO1"}
------WebKitFormBoundarynU961NKt3K534rCg
Content-Disposition: form-data; name="file"; filename="2013-11-16 21.19.59.jpg"
Content-Type: image/jpeg 

As you can see the request clearly has the "profile" part. From my debugging, the issue is that the "profile" request part does not have the "Content-type" set, and DefaultMultipartHttpServletRequest has the below method that requires it to be set and if it returns null the entire request fails with the above error.

@Override
public HttpHeaders getMultipartHeaders(String paramOrFileName) {
String contentType = getMultipartContentType(paramOrFileName);
if (contentType != null) {
 HttpHeaders headers = new HttpHeaders();
 headers.add(CONTENT_TYPE, contentType);
 return headers;
}
else {
 return null;
}
}

Trouble is is that I can't seem to find a way to set the content-type on a FormData submit in the browser for each part and seems to be something I can't set, and Spring seems to require it.

Any tips on how to fix this or if this is a bug?

Thanks

Gayathri
  • 894
  • 6
  • 19
Zoheb Sait
  • 41
  • 2
  • 2
  • Have you fixed this? I think your `Content-Disposition: form-data; name="profile"` part just needs an additional `Content-Type: application/json` (just like the image) – Benjamin M Jan 24 '14 at 07:44

2 Answers2

2

I see two options to solve the issue:

  1. On the client: Add the JSON as Blob to FormData, as mentioned here. Background: Blob allows setting the content type (example with angular js):

    var formData = new FormData();
    formData.append('profile', new Blob([angular.toJson(profile)], {
      type: "application/json"}
    ));
    
  2. Alternativly on the server (not recommended): overwrite the getMultipartHeaders method of DefaultMultipartHttpServletRequest and configure this in spring. If you are using CommonsMultipartResolver you need to overwrite it as well (due to missing dependency injection point):

    new DefaultMultipartHttpServletRequest() {
    
        @Override
        public HttpHeaders getMultipartHeaders(String paramOrFileName) {
            // your code here
        }
    }
    
Community
  • 1
  • 1
seb.wired
  • 456
  • 1
  • 3
  • 12
0

I was just battling this issue and my solution was to stop using @RequestPart and use @RequestParam instead. If I'm understanding the doc for @RequestPart correctly, it only works out of the box for a few types (such as MultipartFile) but others require an HttpMessageConverter. Also make sure you have a MultipartResolver bean declared. Recommend that it return a CommonsMultipartResolver.

jgreen
  • 1,132
  • 2
  • 14
  • 18