Ich möchte eine Datei mit einigen JSON-Daten mit Spring MVC veröffentlichen. Also habe ich einen Restservice als entwickelt
@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);
}
Wenn ich eine Anfrage vom Rest-Client mit sende
content-Type = multipart/form-data or multipart/mixed
, erhalte ich die nächste Ausnahme:
org.springframework.web.multipart.support.MissingServletRequestPartException
Kann mir jemand bei der Lösung dieses Problems helfen?
Kann ich @RequestPart
sowohl Multipart als auch JSON an einen Server senden?
json
spring
spring-mvc
Sunil Kumar
quelle
quelle
org.springframework.web.multipart.commons.CommonsMultipartResolver
in Ihrem Servlet-Kontext ein angegeben?Antworten:
So habe ich Spring MVC Multipart Request mit JSON-Daten implementiert.
Multipart-Anfrage mit JSON-Daten (auch Mixed Multipart genannt):
Basierend auf dem RESTful-Dienst in Spring 4.0.2 Release kann eine HTTP-Anforderung mit dem ersten Teil als XML- oder JSON-formatierte Daten und dem zweiten Teil als Datei mit @RequestPart ausgeführt werden. Unten finden Sie die Beispielimplementierung.
Java-Snippet:
Der Restdienst in Controller verfügt über gemischte @RequestPart- und MultipartFile-Dateien, um eine solche Multipart + JSON-Anforderung zu bedienen.
@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-Snippet (JavaScript):
Erstellen Sie ein FormData-Objekt.
Hängen Sie die Datei mit einem der folgenden Schritte an das FormData-Objekt an.
formData.append("file", document.forms[formName].file.files[0]);
formData.append("file", myFile, "myfile.txt");
ODERformData.append("file", myBob, "myfile.txt");
Erstellen Sie einen Blob mit den stringifizierten JSON-Daten und hängen Sie ihn an das FormData-Objekt an. Dies bewirkt, dass der Inhaltstyp des zweiten Teils in der mehrteiligen Anforderung "application / json" anstelle des Dateityps ist.
Senden Sie die Anfrage an den Server.
Details anfordern :
Content-Type: undefined
. Dies bewirkt, dass der Browser den Inhaltstyp auf Mehrteil- / Formulardaten setzt und die Grenze korrekt ausfüllt. Wenn Sie Content-Type manuell auf Multipart- / Formulardaten einstellen, wird der Grenzparameter der Anforderung nicht ausgefüllt.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" }));
Anfragedetails:
method: "POST", headers: { "Content-Type": undefined }, data: formData
Nutzlast anfordern:
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--
quelle
processData: false, contentType: false
mitJQuery $ajax()
Required request part file is not present
@NotBlank
Anmerkung zum Parameter der MultipartFile-Methode prüft nicht, ob die Datei leer ist. Es ist weiterhin möglich, Dokumente mit 0 Bytes hochzuladen.Das muss funktionieren!
Client (eckig):
$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
quelle
Wie die Dokumentation sagt:
quelle
Wir haben in unseren Projekten gesehen, dass eine Post-Anfrage mit JSON und Dateien viel Verwirrung zwischen den Frontend- und Backend-Entwicklern verursacht, was zu unnötiger Zeitverschwendung führt.
Hier ist ein besserer Ansatz: Konvertieren Sie das Datei-Byte-Array in eine Base64-Zeichenfolge und senden Sie es in 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()); .... }
JS-Code zum Konvertieren der Datei in eine Base64-Zeichenfolge:
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); };
quelle