1

Azureストレージからオブジェクトをストリーミングするためにapache async http clientを使用しています。

ストリームが関連付けられている HttpResponse オブジェクトを返すだけで済みます。私のクライアントは、ファイルをローカルに保存するために実際にそのストリームから読み取る必要があります。

したがって、Apache Async クライアントは BasicAsyncResponseConsumer を使用します。これは、完了したコールバックを呼び出す前に、ファイル全体をローカル メモリに実際にバッファリングします。

AbstractAsyncResponseConsumer の独自の実装を作成して、実際に最初に保存するのではなく、応答本文をストリーミングできるようにしようとしていますが、今までそうすることができませんでした。

参照用の基本的な消費者クラスは次のとおりです->

public class MyConsumer extends` AbstractAsyncResponseConsumer<HttpResponse> {
@Override
protected void onResponseReceived(HttpResponse response) throws HttpException, IOException {

}

@Override
protected void onContentReceived(ContentDecoder decoder, IOControl ioctrl) throws IOException {

}

@Override
protected void onEntityEnclosed(HttpEntity entity, ContentType contentType) throws IOException {

}

@Override
protected HttpResponse buildResult(HttpContext context) throws Exception {
    return null;
}

@Override
protected void releaseResources() {

}

}

そして、リクエストを送信してレスポンスを返すコードは次のとおりです->

public void getFile(HttpRequestBase request) {

    MyConsumer myConsumer = new MyConsumer();
    HttpAsyncRequestProducer producer = 
    HttpAsyncMethods.create(request);
    CompletableFuture<HttpResponse> future = new CompletableFuture<>();
    return Future<HttpResponse> responseFuture = 
    httpclient.execute(producer,myConsumer,                                                                                                                   
    new FutureCallback<HttpResponse>() {
      @Override
      public void completed(HttpResponse result) {
     //This is called only when all the response body has been read
     //future.complete(Result)

      }
      @Override                                                                      
      public void failed(Exception ex) {
      }
      @Override
      public void cancelled() {                                                                       
      }
   });

return future;

 }

HttpResponse オブジェクトの CompletableFuture をクライアントに返します。

HTTP クライアントがすべての応答本文を最初にローカル バッファーで読み取るのを待つべきではありません。

理想的には、応答オブジェクトで提供されるストリームから直接コピーを開始する必要があります。

目的の結果を得るには、コンシューマーの実装に何を追加する必要がありますか?

4

1 に答える 1

1

まだこの問題があるかどうかはわかりませんが、InputStream実際にデータをストリーミングする必要がある場合は、ブロッキング バージョンの Apache HttpClient を使用することをお勧めします。

Java のビルトインInputStreamおよびOutputStreamは本質的にブロッキングであるため、 of を返すことCompletableFutureInputStream本質的に目的を無効にします。BasicAsyncResponseConsumer応答全体をメモリにバッファリングすることは、実際には正しいことです。これが、真にノンブロッキングにする唯一の方法だからです。

あなたが見ることができる別のオプションはですHttpAsyncMethods.createZeroCopyConsumer。それが行うことは、コンテンツを完全にブロックしない方法でファイルに保存することです。次に例を示します。

        try (CloseableHttpAsyncClient client = HttpAsyncClients.createDefault()) {
            client.start();
            final CompletableFuture<HttpResponse> cf = new CompletableFuture<>();
            client.execute(
                    HttpAsyncMethods.createGet("https://example.com"),
                    HttpAsyncMethods.createZeroCopyConsumer(new File("foo.html")),
                    new FutureCallback<HttpResponse>() {
                        @Override
                        public void completed(HttpResponse result) {
                            cf.complete(result);
                        }
                        @Override
                        public void failed(Exception ex) {
                            cf.completeExceptionally(ex);
                        }
                        @Override
                        public void cancelled() {
                            cf.cancel(true);
                        }
                    });
            // When cf completes, the file will be ready.
            // The InputStream inside the HttpResponse will be the FileInputStream of the created file.
        }
于 2019-01-09T18:53:22.163 に答える