Вызов Java HTTP API - потоковая передача и потоковая передача данных

У меня есть служба передачи файлов, написанная на Java и Spring boot, где она передает файлы из источника в пункт назначения без какого-либо локального хранилища.

Он получает дескрипторы InputStream из источника и OutputStream для назначения и эффективно выполняет следующие действия для потоковой передачи файла.

IOUtils.copy(inputStream, outputStream);
Destination InputStream -> IOUtils.copy -> Destination OutputStream

Теперь у меня есть еще одно требование: мне нужно вызвать API шифрования, который принимает поток приложения / окт-и т. Д. И возвращает то же самое. API шифрует данные, когда клиент передает данные, и в то же время возвращает данные в виде потока. Я протестировал API с помощью curl, используя следующую команду:

curl -v -X POST -H "Content-Type:application/octet-stream" -H "Accept:application/octet-stream" --data-binary @test-file -o test-file.enc http://127.0.0.1:1234/encrypt/test-file

Теперь мне нужно интегрировать этот API шифрования с моей исходной службой передачи файлов, где я могу получить дескриптор исходного InputStream, передать его в запрос API, получить InputStream из ответа API и подключить его в свой исходный вызов IOUtils.copy для передачи данные к месту назначения:

Destination InputStream -> Encryption API -> Encrypted InputStream -> IOUtils.copy -> Destination OutputStream

Для реализации вызова API шифрования сначала я пытаюсь создать клиента, передать FileInputStream и извлечь ответ в FileOutputStream. Я пробовал как Apache HTTPClient, так и Spring RestTemplate. В обоих случаях с небольшими файлами он работает, как ожидалось, однако с большими файлами API шифрования получает только часть данных, и кажется, что он застрял там. Исходный вызывающий абонент (служба передачи файлов) также не получает ответа и зависает. Поведение идентично в обеих реализациях.

Реализация с HTTPClient:

InputStream unencryptedInputStream = new FileInputStream("test-file");
HttpClient httpclient = HttpClients.createDefault();

URIBuilder builder = new URIBuilder("http://127.0.0.1:1234/encrypt/test-file");

HttpPost request = new HttpPost(builder.build());
request.setHeader("Content-Type", "application/octet-stream");

InputStreamEntity inputStreamEntity = new InputStreamEntity(unencryptedInputStream, 1064041488);
inputStreamEntity.setContentType("application/octet-stream");
inputStreamEntity.setChunked(true);

request.setEntity(inputStreamEntity );

HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();

InputStream encryptedInputStream = entity.getContent();

OutputStream os = new FileOutputStream("test-file.enc");
IOUtils.copy(encryptedInputStream, os);

Реализация с помощью Spring RestTemplate:

RestTemplate restTemplate = new RestTemplate();

InputStream unencryptedInputStream = new FileInputStream("test-file");

OutputStream encryptedOutputStream = new FileOutputStream("test-file.enc");

SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);

RequestCallback requestCallback = new RequestCallback() {
    @Override
    public void doWithRequest(ClientHttpRequest clientHttpRequest) throws IOException {
        clientHttpRequest.getHeaders().add("Content-type", "application/octet-stream");
        clientHttpRequest.getHeaders().add("Accept", "application/octet-stream");

        IOUtils.copy(unencryptedInputStream, clientHttpRequest.getBody());
    }
};

ResponseExtractor<InputStream> responseExtractor = new ResponseExtractor<InputStream>() {
    @Override
    public InputStream extractData(ClientHttpResponse clientHttpResponse) throws IOException {
        IOUtils.copy(clientHttpResponse.getBody(), encryptedOutputStream);
        return clientHttpResponse.getBody();
    }
};

restTemplate.execute("http://127.0.0.1:1234/encrypt/test-file", HttpMethod.POST, requestCallback, responseExtractor);

Оба случая работают с небольшими файлами, но зависают с большими файлами. Я попытался обернуть запрос IOUtils.copy в потоке "Runnable", но проблема все равно осталась.

0 ответов

Другие вопросы по тегам