Resttemplate form/multipart: image + JSON in POST
If you want to use ByteArrayResource
, simply register a ResourceHttpMessageConverter
.
If you want to use a byte[]
, simply register a ByteArrayHttpMessageConverter
.
The content type of the image part should be an image type, like image/png
, not application/json
.
You can set each individual part's data type with
HttpHeaders partHeaders = new HttpHeaders();
partHeaders.setContentType(MediaType.IMAGE_PNG);
HttpEntity<ByteArrayResource> bytesPart = new HttpEntity<ByteArrayResource>(bytes, partHeaders);
map.add("file", bytesPart);
Create your RestTemplate
by providing your collection of HttpMessageConverter
s
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));
and your outermost HttpEntity
should have a multipart content type
header.setContentType(MediaType.MULTIPART_FORM_DATA);
Related videos on Youtube
TamasGyorfi
Updated on September 15, 2022Comments
-
TamasGyorfi over 1 year
I'm trying to call a rest ws (using resttemplate), that accepts an image and some JSON. However, I don't seem to be able to get it running.
The relevant code is as follows:
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);
Where x is some POJO with all the required JSON annotations (I receive it from another web service, that part works ok).
This thing, however, tells me: HttpMessageNotWritableException: Could not write request: no suitable HttpMessageConverter found for x.
If I change ByteArrayResource to byte[] then I get a 400 Bad Request. If I change the content type to JSON, then ByteArrayResource cannot be serialized into 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"])
I have the following converters configured:
StringHttpMessageConverter, MappingJackson2HttpMessageConverter FormHttpMessageConverter
Any ideas, please? Thanks in advance.
UPDATE
So this is what I currently have after the instructions: I register the converters like this:
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);
Then in the ws call I have:
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);