【问题标题】:Resttemplate form/multipart: image + JSON in POSTResttemplate 表单/多部分:POST 中的图像 + JSON
【发布时间】:2015-03-21 15:04:24
【问题描述】:

我正在尝试调用一个 rest ws(使用 resttemplate),它接受一个图像和一些 JSON。但是,我似乎无法让它运行。

相关代码如下:

    HttpHeaders header = new HttpHeaders();
    header.setContentType(MediaType.MULTIPART_FORM_DATA);

    MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
    ByteArrayResource bytes = new ByteArrayResource(pictureData) {
        @Override
        public String getFilename() {
            return pictureName;
        }
    };
    map.add("x", x);
    map.add("file", bytes);

    HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity(map, header);
    String response =  restTemplate.postForObject(UPLOAD_URL, requestEntity, String.class);

其中 x 是一些带有所有必需 JSON 注释的 POJO(我从另一个 Web 服务接收它,该部分工作正常)。

然而,这件事告诉我:HttpMessageNotWritableException: 无法写入请求:没有为 x 找到合适的 HttpMessageConverter。

如果我将 ByteArrayResource 更改为 byte[],则会收到 400 Bad Request。 如果我将内容类型更改为 JSON,那么 ByteArrayResource 无法序列化为 JSON:

Caused by: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.util.LinkedMultiValueMap["file"]->java.util.LinkedList[0]->a.b.c.["inputStream"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.util.LinkedMultiValueMap["file"]->java.util.LinkedList[0]->a.b.c.["inputStream"])

我配置了以下转换器:

StringHttpMessageConverter,
MappingJackson2HttpMessageConverter
FormHttpMessageConverter

有什么想法吗? 提前致谢。

更新

所以这就是我目前在说明后所拥有的: 我像这样注册转换器:

    RestTemplate restTemplate = new RestTemplate();
    restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
    restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

    FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
        formHttpMessageConverter.addPartConverter(new MappingJackson2HttpMessageConverter());
        formHttpMessageConverter.addPartConverter(new ResourceHttpMessageConverter()); // This is hope driven programming

    restTemplate.getMessageConverters().add(new ResourceHttpMessageConverter());
    restTemplate.getMessageConverters().add(formHttpMessageConverter);

然后在 ws 调用中我有:

    HttpHeaders header = new HttpHeaders();
    header.setContentType(MediaType.APPLICATION_JSON); //Also tried with multipart...

    MultiValueMap<String, Object> multipartRequest = new LinkedMultiValueMap<>();

    ByteArrayResource bytes = new ByteArrayResource(pictureData) {
        @Override
        public String getFilename() {
            return pictureName;
        }
    };

    HttpHeaders xHeader = new HttpHeaders();
    xHeader.setContentType(MediaType.APPLICATION_JSON);
    HttpEntity<X> xPart = new HttpEntity<>(x, xHeader);
    multipartRequest.add("x", xPart);

    HttpHeaders pictureHeader = new HttpHeaders();
    pictureHeader.setContentType(MediaType.IMAGE_PNG);
    HttpEntity<ByteArrayResource> picturePart = new HttpEntity<>(bytes, pictureHeader);
    multipartRequest.add("file", picturePart);

    HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity(multipartRequest, header);
    return restTemplate.postForObject(UPLOAD_URL, requestEntity, String.class);

【问题讨论】:

    标签: java spring rest resttemplate


    【解决方案1】:

    如果您想使用ByteArrayResource,只需注册一个ResourceHttpMessageConverter

    如果您想使用byte[],只需注册ByteArrayHttpMessageConverter

    图片部分的内容类型应该是图片类型,比如image/png,而不是application/json

    您可以使用

    设置每个单独部分的数据类型
    HttpHeaders partHeaders = new HttpHeaders();
    partHeaders.setContentType(MediaType.IMAGE_PNG);
    HttpEntity<ByteArrayResource> bytesPart = new HttpEntity<ByteArrayResource>(bytes, partHeaders);
    
    map.add("file", bytesPart);
    

    通过提供您的HttpMessageConverters 集合来创建您的RestTemplate

    HttpMessageConverter<Object> jackson = new MappingJackson2HttpMessageConverter();
    HttpMessageConverter<Resource> resource = new ResourceHttpMessageConverter();
    FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
    formHttpMessageConverter.addPartConverter(jackson);
    formHttpMessageConverter.addPartConverter(resource); // This is hope driven programming
    
    RestTemplate restTemplate = new RestTemplate(Arrays.asList(jackson, resource, formHttpMessageConverter));
    

    你最外层的HttpEntity应该有一个多部分内容类型

    header.setContentType(MediaType.MULTIPART_FORM_DATA);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-31
      • 1970-01-01
      • 2015-01-25
      • 2014-03-29
      • 1970-01-01
      • 1970-01-01
      • 2015-03-17
      • 2022-01-24
      相关资源
      最近更新 更多