How to Prepare the body of a multipart request in Sprint Boot

How to Prepare the body of a multipart request in Sprint Boot
Photo by Koen Speelman / Unsplash
Prepare the body of a multipart request, resulting in a MultiValueMap<String, HttpEntity>. Parts may be concrete values or via asynchronous types such as Reactor Mono, Flux, and others registered in the ReactiveAdapterRegistry.
This builder is intended for use with the reactive WebClient. For multipart requests with the RestTemplate, simply create and populate a MultiValueMap<String, HttpEntity> as shown in the Javadoc for FormHttpMessageConverter and in the reference docs.

use MultipartBodyBuilder for WebClient

assume you need to post a pdf file and submit some extra information in json together in a single request, you can create the multi part body like below:

    webclient.post()
                .uri(...)
                .headers(...)
                .accept(MediaType.APPLICATION_JSON)
                .bodyValue(createMultiPartBody())
                .retrieve().bodyToMono(SendSignedAgreementResponse.class);
    }

    private MultiValueMap<String, HttpEntity<?>> createMultiPartRelatedBody() {
        MultipartBodyBuilder builder = new MultipartBodyBuilder();
        builder.part("json", json, MediaType.APPLICATION_JSON);
        builder.part("pdf", new MultipartFile().getResource(), MediaType.APPLICATION_PDF);
        return builder.build();
    }

PS: remember set right content type header, or you might got 415 unsupported media type response error.

.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_MIXED_VALUE)
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_VALUE)
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_RELATED_VALUE)

the above code is equal to below POST raw log

use MultiValueMap<String, HttpEntity> for the RestTemplate

MultiValueMap<String, HttpEntity<?>> mixParts = new LinkedMultiValueMap<>();
        HttpHeaders jsonHeaders = new HttpHeaders();
        jsonHeaders.setContentType(MediaType.APPLICATION_JSON);
        try {
            mixParts.add("metadata", new HttpEntity<>(objectMapper.writeValueAsString(response), jsonHeaders));
        } catch (JsonProcessingException e) {
            log.error("Oops!", e);
        }
        HttpHeaders pdfHeaders = new HttpHeaders();
        pdfHeaders.setContentType(MediaType.APPLICATION_PDF);
        mixParts.add("pdf", new HttpEntity<>(new ClassPathResource("contract_unsigned.pdf"), pdfHeaders));
        Response res = restTemplate.exchange(...url, HttpMethod.POST, mixParts,
					Response.class);

References

MultipartBodyBuilder (Spring Framework 6.0.5 API)
declaration: package: org.springframework.http.client, class: MultipartBodyBuilder
Web on Reactive Stack
Web on Servlet Stack

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