Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC Multipart Request with JSON

I want to post a file with some JSON data using Spring MVC. So I've developed a rest service as

@RequestMapping(value = "/servicegenerator/wsdl", method = RequestMethod.POST,consumes = { "multipart/mixed", "multipart/form-data" }) @ResponseBody public String generateWSDLService(@RequestPart("meta-data") WSDLInfo wsdlInfo,@RequestPart("file") MultipartFile file) throws WSDLException, IOException,         JAXBException, ParserConfigurationException, SAXException, TransformerException {     return handleWSDL(wsdlInfo,file); } 

When I send a request from the rest client with content-Type = multipart/form-data or multipart/mixed, I get the next exception: org.springframework.web.multipart.support.MissingServletRequestPartException

Can anyone help me in solving this issue?

Can I use @RequestPart to send both Multipart and JSON to a server?

like image 609
Sunil Kumar Avatar asked Jan 24 '14 09:01

Sunil Kumar


People also ask

How do I pass a multipart file in JSON?

To pass the Json and Multipart in the POST method we need to mention our content type in the consume part. And we need to pass the given parameter as User and Multipart file. Here, make sure we can pass only String + file not POJO + file. Then convert the String to Json using ObjectMapper in Service layer.

What is multipart request in spring?

Multipart requests consist of sending data of many different types separated by a boundary as part of a single HTTP method call. Generally, we can send complicated JSON, XML, or CSV data, as well as transfer multipart file(s) in this request. Examples of multipart files include audio or image files.

How does MultipartFile work in spring?

The file contents are either stored in memory or temporarily on disk. In either case, the user is responsible for copying file contents to a session-level or persistent store as and if desired. The temporary storages will be cleared at the end of request processing.


2 Answers

This is how I implemented Spring MVC Multipart Request with JSON Data.

Multipart Request with JSON Data (also called Mixed Multipart):

Based on RESTful service in Spring 4.0.2 Release, HTTP request with the first part as XML or JSON formatted data and the second part as a file can be achieved with @RequestPart. Below is the sample implementation.

Java Snippet:

Rest service in Controller will have mixed @RequestPart and MultipartFile to serve such Multipart + JSON request.

@RequestMapping(value = "/executesampleservice", method = RequestMethod.POST,     consumes = {"multipart/form-data"}) @ResponseBody public boolean executeSampleService(         @RequestPart("properties") @Valid ConnectionProperties properties,         @RequestPart("file") @Valid @NotNull @NotBlank MultipartFile file) {     return projectService.executeSampleService(properties, file); } 

Front End (JavaScript) Snippet:

  1. Create a FormData object.

  2. Append the file to the FormData object using one of the below steps.

    1. If the file has been uploaded using an input element of type "file", then append it to the FormData object. formData.append("file", document.forms[formName].file.files[0]);
    2. Directly append the file to the FormData object. formData.append("file", myFile, "myfile.txt"); OR formData.append("file", myBob, "myfile.txt");
  3. Create a blob with the stringified JSON data and append it to the FormData object. This causes the Content-type of the second part in the multipart request to be "application/json" instead of the file type.

  4. Send the request to the server.

  5. Request Details:
    Content-Type: undefined. This causes the browser to set the Content-Type to multipart/form-data and fill the boundary correctly. Manually setting Content-Type to multipart/form-data will fail to fill in the boundary parameter of the request.

Javascript Code:

formData = new FormData();  formData.append("file", document.forms[formName].file.files[0]); formData.append('properties', new Blob([JSON.stringify({                 "name": "root",                 "password": "root"                                 })], {                 type: "application/json"             })); 

Request Details:

method: "POST", headers: {          "Content-Type": undefined   }, data: formData 

Request Payload:

Accept:application/json, text/plain, */* Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryEBoJzS3HQ4PgE1QB  ------WebKitFormBoundaryvijcWI2ZrZQ8xEBN Content-Disposition: form-data; name="file"; filename="myfile.txt" Content-Type: application/txt   ------WebKitFormBoundaryvijcWI2ZrZQ8xEBN Content-Disposition: form-data; name="properties"; filename="blob" Content-Type: application/json   ------WebKitFormBoundaryvijcWI2ZrZQ8xEBN-- 
like image 107
Sunil Kumar Avatar answered Sep 19 '22 07:09

Sunil Kumar


This must work!

client (angular):

$scope.saveForm = function () {       var formData = new FormData();       var file = $scope.myFile;       var json = $scope.myJson;       formData.append("file", file);       formData.append("ad",JSON.stringify(json));//important: convert to JSON!       var req = {         url: '/upload',         method: 'POST',         headers: {'Content-Type': undefined},         data: formData,         transformRequest: function (data, headersGetterFunction) {           return data;         }       }; 

Backend-Spring Boot:

@RequestMapping(value = "/upload", method = RequestMethod.POST)     public @ResponseBody     Advertisement storeAd(@RequestPart("ad") String adString, @RequestPart("file") MultipartFile file) throws IOException {          Advertisement jsonAd = new ObjectMapper().readValue(adString, Advertisement.class); //do whatever you want with your file and jsonAd 
like image 38
mohi Avatar answered Sep 22 '22 07:09

mohi