Reputation: 829
I have a code that makes a POST request for a specific endpoint. This code is using Apache's HttpClient
and I would like to start using the native HttpClient
from Java (JDK11). But I didn't understand how to specify the parameters of my request.
This is my code using Apache Httpclient:
var path = Path.of("file.txt");
var entity = MultipartEntityBuilder.create()
.addPart("file", new FileBody(path.toFile()))
.addTextBody("token", "<any-token>")
.build();
And the code using HttpClient
:
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://myendpoint.com/"))
.POST( /* How can I set the parameters here? */ );
How can I set file
and token
parameters?
Upvotes: 16
Views: 13556
Reputation: 25136
Unfortunately the Java 11 HTTP client does not provide any convenient support for multipart kind of body. But we can build custom implementation on top of it:
Map<Object, Object> data = new LinkedHashMap<>();
data.put("token", "some-token-value");
data.put("file", File.createTempFile("temp", "txt").toPath());
// add extra parameters if needed
// Random 256 length string is used as multipart boundary
String boundary = new BigInteger(256, new Random()).toString();
HttpRequest.newBuilder()
.uri(URI.create("http://example.com"))
.header("Content-Type", "multipart/form-data;boundary=" + boundary)
.POST(ofMimeMultipartData(data, boundary))
.build();
public HttpRequest.BodyPublisher ofMimeMultipartData(Map<Object, Object> data,
String boundary) throws IOException {
// Result request body
List<byte[]> byteArrays = new ArrayList<>();
// Separator with boundary
byte[] separator = ("--" + boundary + "\r\nContent-Disposition: form-data; name=").getBytes(StandardCharsets.UTF_8);
// Iterating over data parts
for (Map.Entry<Object, Object> entry : data.entrySet()) {
// Opening boundary
byteArrays.add(separator);
// If value is type of Path (file) append content type with file name and file binaries, otherwise simply append key=value
if (entry.getValue() instanceof Path) {
var path = (Path) entry.getValue();
String mimeType = Files.probeContentType(path);
byteArrays.add(("\"" + entry.getKey() + "\"; filename=\"" + path.getFileName()
+ "\"\r\nContent-Type: " + mimeType + "\r\n\r\n").getBytes(StandardCharsets.UTF_8));
byteArrays.add(Files.readAllBytes(path));
byteArrays.add("\r\n".getBytes(StandardCharsets.UTF_8));
} else {
byteArrays.add(("\"" + entry.getKey() + "\"\r\n\r\n" + entry.getValue() + "\r\n")
.getBytes(StandardCharsets.UTF_8));
}
}
// Closing boundary
byteArrays.add(("--" + boundary + "--").getBytes(StandardCharsets.UTF_8));
// Serializing as byte array
return HttpRequest.BodyPublishers.ofByteArrays(byteArrays);
}
Here's working example on Github (you need to change VirusTotal API key)
Upvotes: 18
Reputation: 3268
The HttpClient
doesn't provide any high level API to compose or format data in POST requests. You could either compose and format your post data manually, and then use either one of BodyPublishers.ofString()
, BodyPublishers.ofInputStream()
, or BodyPublishers.ofByteArrays()
etc... to send it, or write your own implementation of BodyPublisher
.
Upvotes: 0