Spring MVC Multipart Request with JSON Spring MVC Multipart Request with JSON spring spring

Spring MVC Multipart Request with JSON


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"})@ResponseBodypublic 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------WebKitFormBoundaryvijcWI2ZrZQ8xEBNContent-Disposition: form-data; name="file"; filename="myfile.txt"Content-Type: application/txt------WebKitFormBoundaryvijcWI2ZrZQ8xEBNContent-Disposition: form-data; name="properties"; filename="blob"Content-Type: application/json------WebKitFormBoundaryvijcWI2ZrZQ8xEBN--


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


As documentation says:

Raised when the part of a "multipart/form-data" request identified by its name cannot be found.

This may be because the request is not a multipart/form-data either because the part is not present in the request, or because the web application is not configured correctly for processing multipart requests -- e.g. no MultipartResolver.