Как определить несколько параметров для запроса POST, используя Java 11 HTTP Client
У меня есть код, который делает запрос POST для конкретной конечной точки. Этот код использует Apache HttpClient
и я хотел бы начать использовать родной HttpClient
с Java (JDK11). Но я не понял, как указать параметры моего запроса.
Это мой код с использованием Apache Httpclient:
var path = Path.of("file.txt");
var entity = MultipartEntityBuilder.create()
.addPart("file", new FileBody(path.toFile()))
.addTextBody("token", "<any-token>")
.build();
И код, использующий HttpClient
:
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://myendpoint.com/"))
.POST( /* How can I set the parameters here? */ );
Как я могу установить file
а также token
параметры?
2 ответа
К сожалению, HTTP-клиент Java 11 не предоставляет удобной поддержки для составных частей тела. Но мы можем построить собственную реализацию поверх этого:
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);
}
Вот рабочий пример на Github (вам нужно изменить ключ VirusTotal API)
HttpClient
не предоставляет API высокого уровня для создания или форматирования данных в запросах POST. Вы можете либо составить и отформатировать свои данные поста вручную, а затем использовать один из BodyPublishers.ofString()
, BodyPublishers.ofInputStream()
, или же BodyPublishers.ofByteArrays()
и т.д.... чтобы отправить его или написать собственную реализацию BodyPublisher
,