Quiero publicar un archivo con algunos datos JSON usando Spring MVC. Así que desarrollé 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 resto del cliente 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 Multipart y JSON a un servidor?
json
spring
spring-mvc
Sunil Kumar
fuente
fuente
org.springframework.web.multipart.commons.CommonsMultipartResolver
en su contexto de servlet?Respuestas:
Así es como implementé Spring MVC Multipart Request con JSON Data.
Solicitud multiparte con datos JSON (también denominada multiparte mixta):
Basado en el servicio RESTful en Spring 4.0.2 Release, la solicitud HTTP con la primera parte como datos formateados en XML o JSON y la segunda parte como un archivo se puede lograr con @RequestPart. A continuación se muestra la implementación de muestra.
Fragmento de Java:
El servicio de descanso en Controller habrá mezclado @RequestPart y MultipartFile para atender 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 de front-end (JavaScript):
Cree un objeto FormData.
Agregue el archivo al objeto FormData siguiendo uno de los pasos siguientes.
formData.append("file", document.forms[formName].file.files[0]);
formData.append("file", myFile, "myfile.txt");
OformData.append("file", myBob, "myfile.txt");
Cree un blob con los datos JSON en cadena y añádalo al objeto FormData. Esto hace que el tipo de contenido de la segunda parte de la solicitud multiparte sea "application / json" en lugar del tipo de archivo.
Envía la solicitud al servidor.
Detalle de la información:
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 en 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
Solicitar 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--
fuente
processData: false, contentType: false
conJQuery $ajax()
Required request part file is not present
@NotBlank
anotación en el parámetro del método MultipartFile no verificará si el archivo está vacío. Todavía es posible cargar documentos con 0 bytes.¡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; } };
Bota de resorte trasero:
@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
fuente
Como dice la documentación:
fuente
Hemos visto en nuestros proyectos que una solicitud de publicación con JSON y archivos está creando mucha confusión entre los desarrolladores de frontend y backend, lo que lleva a una pérdida de tiempo innecesaria.
Aquí hay un mejor enfoque: convierta la matriz de bytes del archivo a una cadena Base64 y envíelo en JSON.
public Class UserDTO { private String firstName; private String lastName; private FileDTO profilePic; } public class FileDTO { private String base64; // just base64 string is enough. If you want, send additional details private String name; private String type; private String lastModified; } @PostMapping("/user") public String saveUser(@RequestBody UserDTO user) { byte[] fileBytes = Base64Utils.decodeFromString(user.getProfilePic().getBase64()); .... }
Código JS para convertir un archivo a una cadena base64:
var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function () { const userDTO = { firstName: "John", lastName: "Wick", profilePic: { base64: reader.result, name: file.name, lastModified: file.lastModified, type: file.type } } // post userDTO }; reader.onerror = function (error) { console.log('Error: ', error); };
fuente