415通过REST模板发送json文件时不支持的媒体类型

我试图通过REST模板发送一个json文件。 当我通过POST man发送它作为MULTIPART_FORM_DATA时,它工作正常。 我应该给出的名称是具体的(比方说aaa )。 附上截图 截图 POSTMAN。 但是当我在另一个stackoverflow post中指定的代码中尝试相同时,我得到415 Unsupported Media Type错误

org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) ~[spring-web-4.1.9.RELEASE.jar:4.1.9.RELEASE] at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:616) ~[spring-web-4.1.9.RELEASE.jar:4.1.9.RELEASE] at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:572) ~[spring-web-4.1.9.RELEASE.jar:4.1.9.RELEASE] at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:532) ~[spring-web-4.1.9.RELEASE.jar:4.1.9.RELEASE] at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:332) ~[spring-web-4.1.9.RELEASE.jar:4.1.9.RELEASE] at 

请不要将其标记为重复,因为指定的答案对我不起作用。 不共享代码,因为我的代码与此完全相同,除了

 requestParamerterMap.add("attachment", resource); 

我的代码在哪里

 requestParamerterMap.add("aaa", resource); 

从服务器端调试后,看起来请求正在向服务器伸出。 我能够在服务器端看到以下错误:

 [{error=Unsupported Media Type, exception=org.springframework.web.HttpMediaTypeNotSupportedException, message=Content type 'application/octet-stream' not supported, status=415, timestamp=1532557180124}] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@74d4827a] 

所以,从服务器端日志,我不知道内容类型在哪里被添加为application / octet-stream,因为我已将内容类型设置为

 headers.setContentType(MediaType.MULTIPART_FORM_DATA); 

以下是服务器控制器的代码。 服务器端代码使用Spring启动。

  @RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE,consumes = {"multipart/form-data"}) @ResponseBody public MyResponse uploadPhoto(@RequestPart(value = "aaa", required = false) Optional myRequest, @RequestPart(value = "file", required = false) Optional file, HttpServletRequest request) { //some logic return myResponse; } 

服务器代码有一个拦截器,我可以看到我的请求的内容类型为multipart / form-data。 它没有到达RestController

当我在2种情况下调试服务器端代码时:

  1. POSTMAN请求

在此处输入图像描述

  1. 客户端代码请求

在此处输入图像描述

有一件事我发现,当我从POSTMAN发帖时,文件iteam的内容类型为application / json,当请求来自客户端代码时,内容类型是application / octet-stream

在我的客户端代码中,我正在创建JSONObject

 JSONObject json = new JSONObject(); json.append("myKey", "myValue"); 

并将其转换为字节数组

 json.toString().getBytes("UTF-8") 

然后我跟着这个 。 我的代码的不同之处在于,我将JSONObject作为字节流发送,因为我无法创建文件(性能问题)。

我不能将JSONObject作为字符串发送,因为服务器期望文件和aaa的多部分表单数据

我已经创建了restTemplate

  public RestTemplate myRestTemplate() { SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setReadTimeout(HTTP_CLIENT_TIMEOUT); requestFactory.setConnectTimeout(HTTP_CLIENT_TIMEOUT); RestTemplate restTemplate = new RestTemplate(requestFactory); List<HttpMessageConverter> messageConverters = new ArrayList<HttpMessageConverter>(); messageConverters.add(new FormHttpMessageConverter()); messageConverters.add(new StringHttpMessageConverter()); restTemplate.setMessageConverters(messageConverters); return restTemplate; 

以下是调用服务的客户端代码:

 public Optional callService(byte[] multipartFile) { MultiValueMap body = new LinkedMultiValueMap(); InputStream stream = new ByteArrayInputStream(multipartFile); MultipartByteArrayResource resource = new MultipartByteArrayResource(multipartFile,fileName); body.add("aaa", resource); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity<MultiValueMap> requestEntity = new HttpEntity(body, headers); try { response = restTemplate.postForObject(url, requestEntity , String.class); } catch (Exception exception) { LOG.error("Error", exception); return Optional.empty(); } } public class MultipartInputStreamFileResource extends InputStreamResource { private final String filename; MultipartInputStreamFileResource(InputStream inputStream, String filename) { super(inputStream); this.filename = filename; } @Override public String getFilename() { return this.filename; } @Override public long contentLength() throws IOException { return -1; // we do not want to generally read the whole stream into memory ... } } 

当我发送文件时,相同的代码工作(注释文件aaa是两个不同的东西,虽然两者都是服务器端的multipart / form-data文件只是一个任何时间文件(image / text / pdf)但是aaajson数据文件

经过多次调试后,我观察到的是服务器端控制器期望文件内容为json,因为Jackson尝试将该json反序列化为MyRequest对象。 当我从POSTMAN发送post时,它的json内容如此按预期工作,但是从客户端代码,内容是byteArray ,并且它没有反序列化到MyRequest对象。 不知道如何解决这个问题

最后我解决了这个问题。 如上所述,从POSTMAN到代码发送请求时,具有不同内容类型的多部分文件是我开始的地方。 如果有人有任何问题,我会详细解释。

  public Optional save(byte[] multipartFile, String fileName) { MultiValueMap body = new LinkedMultiValueMap<>(); Resource content = new MultipartByteArrayResource(multipartFile , fileName); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity requestEntityBody = new HttpEntity(content, headers); body.add("aaa", requestEntityBody); String result = ""; JSONParser parser = new JSONParser(); JSONObject json = null; HttpHeaders requestHeaders = new HttpHeaders(); HttpEntity> requestEntity = new HttpEntity<>(body, requestHeaders); ResponseEntity response = null; try { RestTemplate restTemplate = customizeRestTemplate(); //I have defined this in different config file in my actual code response = restTemplate.exchange(url , HttpMethod.POST , requestEntity , String.class); result = (response != null && response.getBody() != null) ? response.getBody().toString() : result; json = (JSONObject) parser.parse(result); LOG.info( "Response:", response ); } catch (Exception exception) { LOG.error("Error , exception); return Optional.empty(); } return Optional.ofNullable(json); } public class MultipartByteArrayResource extends ByteArrayResource{ private String fileName; public MultipartByteArrayResource(byte[] byteArray , String filename) { super(byteArray); this.fileName = filename; } public String getFilename() { return fileName; } public void setFilename(String fileName) { this.fileName= fileName; } } public RestTemplate customizeRestTemplate() { SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setReadTimeout(10000); requestFactory.setConnectTimeout(10000); RestTemplate restTemplate = new RestTemplate(requestFactory); List> messageConverters = new ArrayList>(); messageConverters.add(new FormHttpMessageConverter()); messageConverters.add(new StringHttpMessageConverter()); restTemplate.setMessageConverters(messageConverters); return restTemplate; } } 

服务器端exception由org.springframework.http.converter.json.MappingJackson2HttpMessageConverter 。 Jackson是一个JSON库,Spring使用MessageConverter来格式化请求和响应。

当服务器有@Produces(APPLICATION_JSON)注释时,客户端是否可以发送“Accept:application / octet-stream”? 这意味着服务器处理请求并且仅在发送响应时出现问题。 您可以在服务器中添加一些log.info()语句来validation这一点。