Comment traiter une demande en plusieurs parties composée d’un fichier et d’un object JSON dans un service reposant de Spring?

J’ai la ressource suivante (implémentée avec Spring 4.05.RELEASE) qui accepte un fichier et un object JSON:

(PS activityTemplate est une classe d’entités sérialisables)

... @RequestMapping(value="/create", method=RequestMethod.POST) public @ResponseBody ActivityTemplate createActivityTemplate( @RequestPart ActivityTemplate activityTemplate, @RequestPart MultipartFile jarFile) { //process the file and JSON } ... 

et c’est la forme que je teste de:

 
JSON:
File to upload:

et c’est l’erreur que j’ai:

  There was an unexpected error (type=Unsupported Media Type, status=415). Content type 'application/octet-stream' not supported 

Alors, comment devrais-je faire en sorte que la ressource accepte l’object JSON dans le cadre d’une demande multipart ou devrais-je envoyer le formulaire différemment?

Cela m’a pris deux jours pour travailler pour moi!

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.ssortingngify(json));//important: convert to ssortingng JSON! var req = { url: '/upload', method: 'POST', headers: {'Content-Type': undefined}, data: formData, transformRequest: function (data, headersGetterFunction) { return data; } }; 

Spring (Boot):

 @RequestMapping(value = "/upload", method = RequestMethod.POST) public @ResponseBody Advertisement storeAd(@RequestPart("ad") Ssortingng adSsortingng, @RequestPart("file") MultipartFile file) throws IOException { Advertisement jsonAd = new ObjectMapper().readValue(adSsortingng, Advertisement.class); //do whatever you want with your file and jsonAd 

J’espère que cela devrait vous aider. Vous devez définir la limite dans votre demande pour informer la demande HTTP. est simple; Vous trouverez une brève introduction au format en plusieurs parties dans le lien ci-dessous.

HTML 4.01 Spécification pour multipart

L’exemple suivant illustre le codage ” multipart / form-data “. Si l’ object Json est ” MyJsonObj ” et que le fichier à envoyer est ” myfile.txt “, l’agent d’utilisateur peut renvoyer les données suivantes:

 Content-Type: multipart/form-data; boundary=MyBoundary --MyBoundary Content-Disposition: form-data; name="myJsonSsortingng" Content-Type: application/json MyJsonObj //Your Json Object goes here --MyBoundary Content-Disposition: form-data; name="files"; filename="myfile.txt" Content-Type: text/plain ... contents of myfile.txt ... --MyBoundary-- 

ou si vos fichiers sont de type image avec le nom ” image.gif ” alors,

 --MyBoundary Content-Disposition: file; filename="image.gif" Content-Type: image/gif Content-Transfer-Encoding: binary ...contents of image.gif... --MyBoundary-- 

Vous spécifiez une boundary dans l’en Content-Type header afin que le serveur sache comment fractionner les données envoyées.

Donc, vous devez essentiellement sélectionner une valeur de limite pour:

  • Utilisez une valeur qui n’apparaîtra pas dans les données HTTP envoyées au serveur comme 'AaB03x' .
  • Soyez cohérent et utilisez la même valeur sur toute la demande.

Vous n’avez pas donné les noms param à votre @RequestPart s?

 public @ResponseBody ActivityTemplate createActivityTemplate( @RequestPart("activityTemplate") ActivityTemplate activityTemplate, @RequestPart("file") MultipartFile jarFile) { //process the file and JSON } 

Remarque: n’oubliez pas d’inclure le fichier .js (mappeur jackson) .jar ( mappe votre Json à ActivityTemplate ) dans votre chemin d’access aux classes .

Ne pourriez-vous pas changer votre

 @RequestMapping(value="/create", method=RequestMethod.POST) 

à

 @RequestMapping(value="/create", method=RequestMethod.POST, consumes ={"multipart/form-data"}) 

Le type de contenu par défaut est ‘application / octet-stream’. Puisque vous téléchargez le fichier jar et JSON, le type de contenu doit être défini dans l’annotation @RequestMapping comme suit:

 @RequestMapping(value="/create", method=RequestMethod.POST, headers="content-type=application/json,application/java-archive") 

Le message d’erreur indique qu’il n’y a pas de HttpMessageConverter enregistré pour une partie multi-partie / MIME du type de contenu: application / octet-stream. Cependant, votre paramètre jarFile est probablement correctement identifié en tant qu’application / octet-stream. Je suppose donc que le mappage des parameters ne correspond pas.

Donc, essayez d’abord de définir le même nom pour le paramètre et l’élément d’entrée du formulaire.

Un autre problème est que le JSON est téléchargé en tant que valeur (régulière) d’une entrée de texte dans le formulaire, et non en tant que partie distincte du multi-partie / MIME. Donc, aucun en-tête de type de contenu ne lui est associé pour savoir que Spring doit utiliser le désérialiseur JSON. Vous pouvez utiliser @RequestParam place et enregistrer un convertisseur spécifique comme dans cette réponse: paramètre JSON dans le contrôleur MVC Spring

cela peut vous aider, lors de la réception de MultipartFile, vous devez définir l’en-tête de requête content-type sur “multipart / form-data”, puis dans votre contrôleur, utilisez consumes = “multipart / form-data”, également utilisé pour mapper notre requête à notre méthode dans le contrôleur.

Si vous souhaitez recevoir des données JSON, il est préférable d’envoyer une requête sous la forme de JSONSsortingng, il suffit de recevoir cette chaîne jsonssortingng, puis de la convertir au format object json puis d’utiliser cet object pour vos opérations.

vérifier ci-dessous le code:

 @RequestMapping(value="/savingImg", method=RequestMethod.POST, consumes="multipart/form-data", produces="application/json") public ResponseEntity savingAppIMgDtlss( @RequestParam(value="f1", required = false) MultipartFile f1 , @RequestParam(value="f2", required = false) MultipartFile f2 , @RequestParam(value="f3", required = false) MultipartFile f3 , @RequestParam(value="f4", required = false) MultipartFile f4 , @RequestParam(value="f5", required = false) MultipartFile f5 , @RequestParam(value="f6", required = false) MultipartFile f6 , @RequestParam(value="f7", required = false) MultipartFile f7 , @RequestParam(value="f8", required = false) MultipartFile f8 ,@RequestParam("data") Ssortingng jsonSsortingng) throws Exception , ParseException { try{ JSONObject gstcTranObj = new JSONObject(); //converting JSONSsortingng to JSON net.sf.json.JSONObject jsonDtls = net.sf.json.JSONObject.fromObject(jsonSsortingng); System.out.println("f1::"+f1.getOriginalFilename()); System.out.println("f2::"+f2.getOriginalFilename()); System.out.println("f3::"+f3.getOriginalFilename()); System.out.println("f4::"+f4.getOriginalFilename()); System.out.println("f5::"+f5.getOriginalFilename()); System.out.println("f6::"+f6.getOriginalFilename()); System.out.println("f7::"+f7.getOriginalFilename()); System.out.println("f8::"+f8.getOriginalFilename()); } catch (Exception e) { e.printStackTrace(); return new ResponseEntity<>("Failed",HttpStatus.NOT_FOUND); }finally{ } return new ResponseEntity<>("Success", HttpStatus.OK); } }