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

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