Solicitud de múltiples partes de Spring MVC con JSON

Quiero publicar un archivo con algunos datos JSON usando Spring MVC. Así que he desarrollado un servicio de descanso como

@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); } 

Cuando envío una solicitud del cliente de reposo con content-Type = multipart/form-data or multipart/mixed , obtengo la siguiente excepción: org.springframework.web.multipart.support.MissingServletRequestPartException

¿Alguien puede ayudarme a resolver este problema?

¿Puedo usar @RequestPart para enviar tanto Multipart como JSON a un servidor?

Así es como implementé Spring MVC Multipart Request con JSON Data.

Solicitud de múltiples partes con datos JSON (también llamado Mixed Multipart):

En base al servicio RESTful en la versión Spring 4.0.2, la solicitud HTTP con la primera parte como datos formateados XML o JSON y la segunda parte como un archivo se puede lograr con @RequestPart. A continuación se muestra la implementación de la muestra.

Fragmento de Java:

El servicio de reposo en Controller habrá mezclado @RequestPart y MultipartFile para servir dicha solicitud Multipart + JSON.

 @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); } 

Fragmento del front-end (JavaScript):

  1. Crea un objeto FormData.

  2. Agregue el archivo al objeto FormData usando uno de los pasos a continuación.

    1. Si el archivo se ha cargado utilizando un elemento de entrada de tipo “archivo”, añádalo al objeto FormData. formData.append("file", document.forms[formName].file.files[0]);
    2. Agregue directamente el archivo al objeto FormData. formData.append("file", myFile, "myfile.txt"); O formData.append("file", myBob, "myfile.txt");
  3. Crea un blob con los datos JSON codificados y añádelo al objeto FormData. Esto hace que el tipo de contenido de la segunda parte en la solicitud multiparte sea “aplicación / json” en lugar del tipo de archivo.

  4. Envía la solicitud al servidor.

  5. Pedir detalles:
    Content-Type: undefined . Esto hace que el navegador establezca Content-Type en multipart / form-data y complete el límite correctamente. La configuración manual de Content-Type a multipart / form-data no completará el parámetro de límite de la solicitud.

Código Javascript:

 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" })); 

Pedir detalles:

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

Solicitud de carga útil:

 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-- 

Esto debe funcionar!

cliente (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; } }; 

Arranque Backend-Spring:

 @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 

Como dice la documentación:

Se genera cuando no se puede encontrar la parte de una solicitud “multipart / form-data” identificada por su nombre.

Esto puede deberse a que la solicitud no es un multipart / form-data porque la parte no está presente en la solicitud o porque la aplicación web no está configurada correctamente para procesar solicitudes de varias partes, por ejemplo, no MultipartResolver.