import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpHeaders; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpRequest.BodyPublishers.Part; import java.net.http.HttpResponse.BodyHandlers; import java.nio.file.Path; import java.util.List; import java.util.Map; import java.util.function.BiPredicate; public class MultipartBodyPublisherTest { public static final BiPredicate ACCEPT_ALL = (x, y) -> true; static final String BOUNDARY = "gc0p4Jq0M2Yt08jU534c0p"; public static void main(String... args) throws Exception { // Alternative #1 var publisher = BodyPublishers.ofMultipart( "the87665boundary", new Part(HttpHeaders.of(Map.of("Content-Type", List.of("text/plain; charset=us-ascii")), ACCEPT_ALL), BodyPublishers.ofString("Hello World!")) ); // Alternative #2 var publisher2 = BodyPublishers.ofMultipart2( "the987654boundary", List.of(Map.entry(HttpHeaders.of(Map.of("Content-Type", List.of("text/plain; charset=us-ascii")), ACCEPT_ALL), BodyPublishers.ofString("Hello World!"))) ); // Alternative #3 var publisher3 = BodyPublishers.ofMultipart3( "the12345boundary", // # part 1 - no explicit headers, implicitly defaults to "text/plain" as per rfc BodyPublishers.ofString("Hello There"), // # part 2 - some text with an explicit content-type header BodyPublishers.multipartPart( HttpHeaders.of(Map.of("Content-Type", List.of("text/plain; charset=us-ascii")), ACCEPT_ALL), BodyPublishers.ofString("blah blah")), // # part 3 - a file BodyPublishers.multipartPart( HttpHeaders.of(Map.of("Content-Disposition", List.of("form-data; name=\"files\"; filename=\"file1.txt\""), "Content-Type", List.of("text/plain")), ACCEPT_ALL), BodyPublishers.ofFile(Path.of("/tmp/fff"))) ); // Alternative #3.1 ( re-stack above with locals ) var part1 = BodyPublishers.ofString("Hello There"); var part2 = BodyPublishers.multipartPart( HttpHeaders.of(Map.of("Content-Type", List.of("text/plain; charset=us-ascii")), ACCEPT_ALL), BodyPublishers.ofString("blah blah")); var part3 = BodyPublishers.multipartPart( HttpHeaders.of(Map.of("Content-Disposition", List.of("form-data; name=\"files\"; filename=\"file1.txt\""), "Content-Type", List.of("text/plain")), ACCEPT_ALL), BodyPublishers.ofFile(Path.of("/tmp/fff"))); var publisher31 = BodyPublishers.ofMultipart3("the12345boundary",part1, part2, part3); // -- var client = HttpClient.newHttpClient(); var request = HttpRequest.newBuilder() .uri(URI.create("http://foo.com/")) // << User sets multipart + boundary explicitly! e.g. // multipart/mixed : multipart/digest : multipart/mixed : multipart/alternative : etc .header("Content-Type", "multipart/mixed; boundary=" + BOUNDARY) .POST(publisher) .build(); client.send(request, BodyHandlers.ofString()); } }