Multipart & Forms¶
Methanol has special BodyPublisher
implementations for multipart uploads & form submission.
Multipart Bodies¶
MultipartBodyPublisher
implements the multipart format. A multipart body has one or more parts.
Each part has a BodyPublisher
for its content and HttpHeaders
that describe it.
MultipartBodyPublisher.Builder
defaults to multipart/form-data
if a multipart MediaType
isn't explicitly specified.
There are special methods for adding parts with a Content-Disposition: form-data
header generated from a field name and an optional file name.
These are referred to as form parts.
// Substitute with your client ID. Visit https://api.imgur.com/oauth2/addclient to get one.
static final String CLIENT_ID = System.getenv("imgur.client.id");
final Methanol client = Methanol.create();
HttpResponse<String> uploadGif() throws IOException, InterruptedException {
var multipartBody = MultipartBodyPublisher.newBuilder()
.textPart("title", "Dancing stick bug")
.filePart("image", Path.of("dancing-stick-bug.gif"), MediaType.IMAGE_GIF)
.build();
return client.send(
MutableRequest.POST("https://api.imgur.com/3/image", multipartBody)
.header("Authorization", "Client-ID " + CLIENT_ID),
BodyHandlers.ofString());
}
If filePart
isn't given a MediaType
, it asks the system for one using the given Path
, falling
back to application/octet-stream
if that doesn't work.
Hint
A part's Content-Type
is automatically added if it's created with a MimeBodyPublisher
.
Generic Form Parts¶
Use builder's formPart
to add a form part from an arbitrary BodyPublisher
. It takes a field name and an optional file name.
// Substitute with your client ID. Visit https://api.imgur.com/oauth2/addclient to get one.
static final String CLIENT_ID = System.getenv("imgur.client.id");
final Methanol client = Methanol.create();
HttpResponse<String> uploadGif() throws IOException, InterruptedException {
var multipartBody = MultipartBodyPublisher.newBuilder()
.textPart("title", "Dancing stick bug")
.formPart(
"image", title + ".png", MoreBodyPublishers.ofMediaType(imagePart, MediaType.IMAGE_PNG))
.build();
return client.send(
MutableRequest.POST("https://api.imgur.com/3/image", multipartBody)
.header("Authorization", "Client-ID " + CLIENT_ID),
BodyHandlers.ofString());
}
Tip
Use MoreBodyPublishers::ofMediaType
to pair an arbitrary BodyPublisher
with its proper MediaType
if you want a Content-Type
header to be specified by the part.
Form Bodies¶
Use FormBodyPublisher
to send form data as a set of URL-encoded queries. Data is added as string name-value pairs.
final Methanol client = Methanol.create();
HttpResponse<String> sendQueries(String url, Map<String, String> queries)
throws IOException, InterruptedException {
var builder = FormBodyPublisher.newBuilder();
queries.forEach(builder::query);
return client.send(MutableRequest.POST(url, builder.build()), BodyHandlers.ofString());
}
Hint
Requests with MultipartBodyPublisher
or FormBodyPublisher
will have their Content-Type
header
added automatically if sent on a Methanol
client.