Spring Controller @RequestBody with file upload is it possible?
Solution 1
You can actually simplify your life here since all you are doing is submitting a form that contains some fields and file. You don't need @RequestBody for what you are trying to do. You can use regular Spring MVC features, so your controller method would look like:
@ResponseBody
public WebResponse<Boolean> updateEUSettings(
Locale locale,
@Valid EUPSettingsWrapper endUserPortalSettingsWrapper,
@RequestParam(value = "file1", required = true) MultipartFile logo
) {
}
The client that submits the request to this controller will need to have a form with enctype="multipart/form-data"
.
In your Spring MVC test you would write something like this:
getMockMvc().perform(fileUpload(uri).file("file1", "some-content".getBytes())
.param("someEuSettingsProperty", "someValue")
.param("someOtherEuSettingsProperty", "someOtherValue")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.MULTIPART_FORM_DATA))
.andExpect(status().isOk());
Solution 2
Please add the following bean in your spring-servlet.xml to add the support for multipart request.
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
Also don't forget to add the dependency for commons-fileupload jar
Solution 3
I couldn't find a way to use @RequestBody.
However, you can do something like this:
@RequestMapping(value = "/uploadStuff", method = RequestMethod.POST)
public MyViewDto doStuff(@RequestPart("json") @Valid MyDto dto,
@RequestPart("file") MultipartFile file) { ... }
You can test it like this:
MockMultipartFile jsonFile = new MockMultipartFile("json", "",
"application/json", "{}".getBytes());
MockMultipartFile dataFile = new MockMultipartFile("file", "foo.zip", "application/octet-stream", bytes);
mockMvc.perform(fileUpload("/uploadStuff")
.file(dataFile)
.file(jsonFile))
.andExpect(status().isOk());
Related videos on Youtube
Yatin
Updated on July 09, 2022Comments
-
Yatin almost 2 years
I have a Controller like this and I want to submit a form with file uploading as well as some form data like label as shown below. Also, I want to do that using @RequestBody so I can use the @Valid annotation on the wrapper as more variables will be added.
public @ResponseBody WebResponse<Boolean> updateEUSettings( final Locale locale, @Validated @ModelAttribute final EUPSettingsWrapper endUserPortalSettingsWrapper) { }
And my wrapper is:
public class EUPSettingsWrapper { private String label; private MultipartFile logo; // getter , setters..etc... }
But I would like to convert it into a @RequestBody from ModelAttributes.
The way I'm trying is by having the file upload separated as request parameter like this:
public @ResponseBody WebResponse<Boolean> updateEUSettings( final Locale locale, @Validated @RequestBody final EUPSettingsWrapper endUserPortalSettingsWrapper, @RequestParam(value = "file1", required = true) final MultipartFile logo) { endUserPortalSettingsWrapper.setLogo(logo); // ... }
In my mock MVC, I am setting:
getMockMvc().perform(fileUpload(uri).file(logo) .accept(MediaType.APPLICATION_JSON) .content(JSONUtils.toJSON(wrapper)) .contentType(MediaType.MULTIPART_FORM_DATA)) .andExpect(status().isOk());
But I'm getting an error like this which says:
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data' not supported
Does anyone have a good idea of how Multipart file uploads can be used with @RequestBody? Anything I am doing wrong above?
-
Pavindu over 2 years
-
-
Kenny Worden almost 6 yearsAlso see this answer for how to set it up in a Java-based configuration: stackoverflow.com/a/29883166/3960852
-
Christos Karapapas about 5 yearsVery interesting, but how does the data looks in the Ajax POST request? Do you create a Object to represent EUPSettingsWrapper and a FormData to represent the MultipartFile and then you assign the FormData to, let's say, obj.logo ? Also do you JSON.stringify() that obj or not?
-
geoand about 5 yearsUnfortunately I don't really remember since the answer is pretty old :)
-
Akshay Naik about 4 yearsorg.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported
-
Dharmendrasinh Chudasama over 3 yearsAnother way is encode your file bytes into base64 and then generated string can be use in request json, generally this patten is not recommended but for special schenarios: {"name":"aa","logo":encodeBase64(fileByteArray)} for encoding follow given url: stackoverflow.com/questions/22172604/…