如何在Spring restful服务中处理由文件和JSON对象组成的多部分请求?

我有以下资源(使用Spring 4.05.RELEASE实现),它接受一个文件和一个JSON对象:

(PS activityTemplate是一个可序列化的实体类)

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

这是我测试的forms:

 
JSON:
File to upload:

这是我得到的错误:

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

那么我该如何让资源接受JSON对象作为multipart请求的一部分,或者我应该以不同的方式发送表单?

这花了我两天时间为我工作!

客户(角度):

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

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 

希望这对你有帮助。 您需要在请求中设置边界以通知HTTP请求。 很简单; 有关多部分格式的简要介绍,请参见以下链接

HTML 4.01多部分规范

以下示例说明了“ multipart / form-data ”编码。 如果Json对象是“ MyJsonObj ”,并且需要发送的文件是“ myfile.txt ”,则用户代理可能会发回以下数据:

 Content-Type: multipart/form-data; boundary=MyBoundary --MyBoundary Content-Disposition: form-data; name="myJsonString" 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-- 

或者如果您的文件是图像类型为“ image.gif ”的图像,那么,

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

您可以在Content-Type header指定boundary ,以便服务器知道如何拆分发送的数据。

所以,你基本上需要选择一个边界值:

  • 使用不会出现在发送到服务器的HTTP数据中的值,如'AaB03x'
  • 保持一致并在整个请求中使用相同的值。

你还没有给你的@RequestPart提供参数名称?

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

注意:不要忘记在类路径中包含jackson mapper .jar( 将Json映射到ActivityTemplate )文件。

你不能改变你的

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

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

默认内容类型是“application / octet-stream”。 由于您要上传jar文件和JSON,因此应在@RequestMapping注释中设置内容类型,如下所示:

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

错误消息表明没有为内容类型的多部分/ MIME部分注册HttpMessageConverter:application / octet-stream。 尽管如此,你的jarFile参数很可能被正确识别为application / octet-stream,所以我假设参数映射不匹配。

因此,首先尝试为参数和表单的输入元素设置相同的名称。

另一个问题是JSON是作为表单中文本输入的(常规)值上传的,而不是作为multi-part / MIME中的单独部分。 所以没有与之关联的内容类型标头,以发现Spring应该使用JSON反序列化器。 您可以使用@RequestParam代替并注册一个特定的转换器,如以下答案: Spring MVC控制器中的JSON参数

这可能会对你有所帮助,在接收MultipartFile时你应该将请求标题内容类型设置为“multipart / form-data”,然后在你的控制器中使用consumes =“multipart / form-data”,消耗也用于将我们的请求映射到我们的方法在控制器中。

如果你想接收JSON数据,最好以JSONString的forms发送请求,只需接收jsonstring,然后转换为json对象格式,然后使用该对象进行操作。

检查以下代码:

 @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") String jsonString) throws Exception , ParseException { try{ JSONObject gstcTranObj = new JSONObject(); //converting JSONString to JSON net.sf.json.JSONObject jsonDtls = net.sf.json.JSONObject.fromObject(jsonString); 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); } }