Как загрузить InputStream через HttpPut из Apache HttpClient 4.x - PullRequest
1 голос
/ 04 апреля 2019

Я пытаюсь загрузить InputStream через HttpPut с помощью Apache HttpClient 4.5.6:

InputStream inputStream = ..
CredentialsProvider provider = ..
HttpClient client = HttpClientBuilder.create()
                .setDefaultCredentialsProvider(provider)
                .build();

HttpPut method = new HttpPut("MY_REMOTE_URL");
InputStreamEntity entity = new InputStreamEntity(inputStream);
method.setEntity(entity);
client.execute(method);

Загрузка требует аутентификации, и в моем случае я не знаю, использовал ли сервердайджест или базовая аутентификация, поэтому клиент автоматически отправляет несколько запросов для определения схемы аутентификации.Но InputStreamEntity не повторяется, что приводит к следующим ошибкам:

org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.

Идея # 1: Буферизация InputStream

Я могу обернуть сущность с помощью BufferedHttpEntity, что делаетэто повторяется:

..
BufferedHttpEntity entity = new BufferedHttpEntity(new InputStreamEntity(inputStream));
method.setEntity(entity);
..

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


Идея № 2: Преимущественная аутентификация

Я могу добавить жестко закодированный заголовок с правильной аутентификацией, чтобы предотвратить повторение запроса.Но, как я уже сказал, я не знаю схему аутентификации.


Идея № 3: Загрузка фиктивной FileEntity для получения контекста (мое текущее решение)

Сначала я загружаю пустой файл, соберите контекст и добавьте его в мой запрос PUT InputStream:

HttpPut testMethod = new HttpPut("MY_REMOTE_DUMMY_URL");
FileEntity testEntity = new FileEntity(testFile);
testMethod.setEntity(testEntity);
HttpContext context = new BasicHttpContext();
client.execute(testMethod, context);

// .. delete the testEntity from server ..

HttpPut method = new HttpPut("MY_REMOTE_URL");
InputStreamEntity entity = new InputStreamEntity(inputStream);
method.setEntity(entity);
client.execute(method, context);

Это работает, но похоже на хак.Должен ли я сделать это?Есть ли альтернативы?

1 Ответ

1 голос
/ 05 апреля 2019

Вместо этого активируйте expect-continue рукопожатие.

HttpClientContext context = HttpClientContext.create();
RequestConfig config = RequestConfig.custom().setExpectContinueEnabled(true).build();
context.setRequestConfig(config);
...