public CompletableFuture<Void> downloadWithResponse(String containerName, String blobName, BlobId blobId,
      boolean autoCreateContainer, OutputStream stream, BlobRange range, DownloadRetryOptions options,
      BlobRequestConditions requestConditions, boolean getRangeContentMd5) {
    // Might as well use same timeout for upload and download
    return FutureUtils.retry(() -> {
      CompletableFuture<Void> completableFuture = new CompletableFuture<>();
      BlockBlobAsyncClient blobAsyncClient = getBlockBlobAsyncClient(containerName, blobName, autoCreateContainer);
      blobAsyncClient.downloadWithResponse(range, options, requestConditions, getRangeContentMd5)
          .subscribe(response -> response.getValue().subscribe(byteBuffer -> {
                try {
                  stream.write(byteBuffer.array());
                } catch (IOException e) {
                  completableFuture.completeExceptionally(e);
                }
              }, completableFuture::completeExceptionally, () -> completableFuture.complete(null)),
              completableFuture::completeExceptionally);
      return completableFuture;
    }, retries, retryPredicate, this::onRetriableError, this::onError);
  }
Downloads a range of bytes from a blob asynchronously into an output stream.
@param containerName name of the Azure container where the blob lives.
@param blobName name of the blob.
@param blobId Ambry {@link BlobId} associated with the {@code fileName}. Null value indicates blobName refers
              to a metadata blob owned by Ambry.
@param autoCreateContainer flag indicating whether to create the container if it does not exist.
@param stream A non-null {@link OutputStream} instance where the downloaded data will be written.
@param range {@link BlobRange}
@param options {@link DownloadRetryOptions}
@param requestConditions {@link BlobRequestConditions}
@param getRangeContentMd5 Whether the contentMD5 for the specified blob range should be returned.
@return a {@link CompletableFuture} of type {@link Void} that will eventually complete when blob is downloaded
        or an exception if an error occurred.
ambry-cloud/src/main/java/com/github/ambry/cloud/azure/StorageClient.java