How to parse Multiparts response body from client side in Spring Boot?

How to parse Multiparts response body from client side in Spring Boot?
Photo by Edgar Chaparro / Unsplash
Default HttpMessageReader for parsing "multipart/form-data" requests to a stream of Parts.
In default, non-streaming mode, this message reader stores the contents of parts smaller than maxInMemorySize in memory, and parts larger than that to a temporary file in fileStorageDirectory.
This reader can be provided to MultipartHttpMessageReader in order to aggregate all parts into a Map.

use toEntityFlux and DefaultPartHttpMessageReader for Reactive stack

Variant of toEntityFlux(Class) with a BodyExtractor.
Params:
bodyExtractor – the BodyExtractor that reads from the response
Type parameters:
– the body element type
Returns:
the ResponseEntity
Since:
5.3.2
    webclient.get()
                .uri(...uri)
                .headers(...headers)
                .retrieve()
                .toEntityFlux((inputMessage, context) -> partReader.read(ResolvableType.forType(byte[].class), inputMessage, Map.of()))
                .map(ResponseEntity::getBody)
                .flatMap(parts -> parts.reduce(MixedResponse.builder(), (body, part) -> {
                    if (part.headers().getContentType().equals(MediaType.APPLICATION_JSON)) {
                        val json = DataBufferUtils.join(part.content())
                                .map(buffer -> {
                                    byte[] bytes = new byte[buffer.readableByteCount()];
                                    buffer.read(bytes);
                                    DataBufferUtils.release(buffer);
                                    return jsonValueSerializer.deserializeValue(new String(bytes),
                                            JSON.class);
                                });
                        body.json(json);
                    }
                    if (part.headers().getContentType().equals(MediaType.APPLICATION_PDF)) {
                        var pdf = DataBufferUtils.join(part.content())
                                .map(buffer -> buffer.asByteBuffer().array());
                        body.pdf(pdf);
                    }
                    return body;
                })
                .map(body -> body.build()));

NOTE that the body contents must be completely consumed, relayed, or released to avoid memory leaks.

custom HttpMessageConverter for the RestTemplate

You might have to custom your own HttpMessageConverter and add into the RestTemplate message converters.

RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().add(new MultiPartMessageConverter(objectMapper));
        final ResponseEntity<ResultModel> responseEntity = restTemplate.getForEntity("http://localhost:" + randomServerPort + "/test", ResultModel.class);
        final ResultModel resultModel = responseEntity.getBody();
        Assertions.assertNotNull(resultModel);
        Assertions.assertEquals(2, resultModel.secondModel.size());
        Assertions.assertEquals("Param1.Value", resultModel.firstModel.param1);
        Assertions.assertEquals("Param2.Value", resultModel.firstModel.param2);

References

HttpMessageConverter (Spring Framework 6.0.5 API)
declaration: package: org.springframework.http.converter, interface: HttpMessageConverter

https://stackoverflow.com/questions/65762857/resttemplate-multipart-form-data-response

Subscribe to Post, Code and Quiet Time.

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe