Многопользовательская загрузка с помощью Apache HttpClient

1. Общий обзор

В этом руководстве мы проиллюстрируем, как выполнить операцию загрузки нескольких частей с помощью HttpClient 5.

1. Общий обзор  В этом руководстве мы проиллюстрируем, как выполнить операцию загрузки нескольких частей с помощью HttpClient 5. 2.

2. Использование метода AddPart

Давайте начнем с рассмотрения объекта MultipartEntityBuilder для добавления частей к Http-объекту, который затем будет загружен с помощью операции POST.

Это универсальный метод добавления частей к HttpEntity, представляющему форму.

Пример 2.1. –
Загрузка формы, состоящей из двух текстовых частей и файла

final File file = new File(url.getPath());
final FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY);
final StringBody stringBody1 = new StringBody("This is message 1", ContentType.MULTIPART_FORM_DATA);
final StringBody stringBody2 = new StringBody("This is message 2", ContentType.MULTIPART_FORM_DATA);

final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.LEGACY);
builder.addPart("file", fileBody);
builder.addPart("text1", stringBody1);
builder.addPart("text2", stringBody2);
final HttpEntity entity = builder.build();

post.setEntity(entity);
try(CloseableHttpClient client = HttpClientBuilder.create()
.build()) {

client.execute(post, response -> {
//do something with response
});
}

Обратите внимание, что мы создаем экземпляр объекта File, также указывая значение ContentType, которое будет использоваться сервером.

Также обратите внимание, что метод AddPart имеет два аргумента, которые действуют как пары ключ/значение для формы. Они актуальны только в том случае, если серверная часть действительно ожидает и использует имена параметров – в противном случае они игнорируются.

3. Использование методов addBinaryBody и addTextBody

Более простой способ создать составную сущность - использовать методы addBinaryBody и AddTextBody. Эти методы работают для загрузки текста, файлов, массивов символов и объектов InputStream. Давайте проиллюстрируем это на простых примерах.

Пример 3.1. –
Загрузка текста и части текстового файла

final File file = new File(url.getPath());
final String message = "This is a multipart post";
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.LEGACY);
builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, TEXTFILENAME);
builder.addTextBody("text", message, ContentType.DEFAULT_BINARY);
final HttpEntity entity = builder.build();
post.setEntity(entity);

try(CloseableHttpClient client = HttpClientBuilder.create()
.build()) {

client.execute(post, response -> {
//do something with response
});
}

Обратите внимание, что объекты File Body и StringBody здесь не нужны.

Также важно отметить, что большинство серверов не проверяют ContentType текстового текста, поэтому метод addTextBody может не указывать значение ContentType.

API addBinaryBody принимает ContentType, но также возможно создать объект только из двоичного тела и имени параметра формы, содержащего файл. Как указывалось в предыдущем разделе, некоторые серверы не распознают файл, если не указано значение ContentType.

Далее мы добавим zip-файл в качестве входного потока, в то время как файл изображения будет добавлен в качестве файлового объекта:

Пример 3.2. –
Загрузка Zip-файла, файла изображения и текстовой части

final URL url = Thread.currentThread()
.getContextClassLoader()
.getResource("uploads/" + ZIPFILENAME);
final URL url2 = Thread.currentThread()
.getContextClassLoader()
.getResource("uploads/" + IMAGEFILENAME);
final InputStream inputStream = new FileInputStream(url.getPath());
final File file = new File(url2.getPath());
final String message = "This is a multipart post";
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.LEGACY);
builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, IMAGEFILENAME);
builder.addBinaryBody("upstream", inputStream, ContentType.create("application/zip"), ZIPFILENAME);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
final HttpEntity entity = builder.build();
post.setEntity(entity);

try(CloseableHttpClient client = HttpClientBuilder.create()
.build()) {

client.execute(post, response -> {
//do something with response
});
}

Обратите внимание, что значение ContentType может быть создано "на лету", как в примере выше для zip-файла.

Наконец, не все серверы распознают части InputStream. Сервер, который мы создали в первой строке кода, распознает входные потоки.

Давайте теперь рассмотрим другой пример, в котором addBinaryBody работает непосредственно с массивом байт:

Пример 3.3. –
Загрузка массива байт и текста

final String message = "This is a multipart post";
final byte[] bytes = "binary code".getBytes();
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.LEGACY);
builder.addBinaryBody("file", bytes, ContentType.DEFAULT_BINARY, TEXTFILENAME);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
final HttpEntity entity = builder.build();
post.setEntity(entity);

try(CloseableHttpClient client = HttpClientBuilder.create()
.build()) {

client.execute(post, response -> {
//do something with response
});
}

Обратите внимание на ContentType, который теперь указывает двоичные данные.

4. Заключение

В этой статье MultipartEntityBuilder представлен как гибкий объект, который предлагает множество вариантов API для создания составной формы.

В примерах также показано, как использовать HttpClient для загрузки HttpEntity, аналогичного объекту form.

Оригинал статьи: https://www.baeldung.com/httpclient-multipart-upload