Source:
public Mono<Response<BlockBlobItem>> uploadWithResponse(Flux<ByteBuffer> data, ParallelTransferOptions parallelTransferOptions, BlobHTTPHeaders headers, Map<String, String> metadata, AccessTier tier, BlobAccessConditions accessConditions) { Objects.requireNonNull(data, "data must not be null"); BlobAccessConditions accessConditionsFinal = accessConditions == null ? new BlobAccessConditions() : accessConditions; final ParallelTransferOptions finalParallelTransferOptions = parallelTransferOptions == null ? new ParallelTransferOptions() : parallelTransferOptions; int blockSize = finalParallelTransferOptions.getBlockSize(); int numBuffers = finalParallelTransferOptions.getNumBuffers(); UploadBufferPool pool = new UploadBufferPool(numBuffers, blockSize); Flux<ByteBuffer> chunkedSource = data.flatMapSequential(buffer -> { if (buffer.remaining() <= blockSize) { return Flux.just(buffer); } int numSplits = (int) Math.ceil(buffer.remaining() / (double) blockSize); return Flux.range(0, numSplits) .map(i -> { ByteBuffer duplicate = buffer.duplicate().asReadOnlyBuffer(); duplicate.position(i * blockSize); duplicate.limit(Math.min(duplicate.limit(), (i + 1) * blockSize)); return duplicate; }); }); return chunkedSource.concatMap(pool::write) .concatWith(Flux.defer(pool::flush)) .flatMapSequential(buffer -> { final String blockId = Base64.getEncoder().encodeToString( UUID.randomUUID().toString().getBytes(UTF_8)); return getBlockBlobAsyncClient().stageBlockWithResponse(blockId, Flux.just(buffer), buffer.remaining(), accessConditionsFinal.getLeaseAccessConditions()) .map(x -> blockId) .doFinally(x -> pool.returnBuffer(buffer)) .flux(); }) .collect(Collectors.toList()) .flatMap(ids -> getBlockBlobAsyncClient().commitBlockListWithResponse(ids, headers, metadata, tier, accessConditions)); }

Target:
public Mono<Response<BlockBlobItem>> uploadWithResponse(Flux<ByteBuffer> data, ParallelTransferOptions parallelTransferOptions, BlobHTTPHeaders headers, Map<String, String> metadata, AccessTier tier, BlobAccessConditions accessConditions) { Objects.requireNonNull(data, "'data' must not be null"); BlobAccessConditions accessConditionsFinal = accessConditions == null ? new BlobAccessConditions() : accessConditions; final ParallelTransferOptions finalParallelTransferOptions = parallelTransferOptions == null ? new ParallelTransferOptions() : parallelTransferOptions; int blockSize = finalParallelTransferOptions.getBlockSize(); int numBuffers = finalParallelTransferOptions.getNumBuffers(); ProgressReceiver progressReceiver = finalParallelTransferOptions.getProgressReceiver(); AtomicLong totalProgress = new AtomicLong(0); Lock progressLock = new ReentrantLock(); UploadBufferPool pool = new UploadBufferPool(numBuffers, blockSize); Flux<ByteBuffer> chunkedSource = data.flatMapSequential(buffer -> { if (buffer.remaining() <= blockSize) { return Flux.just(buffer); } int numSplits = (int) Math.ceil(buffer.remaining() / (double) blockSize); return Flux.range(0, numSplits) .map(i -> { ByteBuffer duplicate = buffer.duplicate().asReadOnlyBuffer(); duplicate.position(i * blockSize); duplicate.limit(Math.min(duplicate.limit(), (i + 1) * blockSize)); return duplicate; }); }); return chunkedSource.concatMap(pool::write) .concatWith(Flux.defer(pool::flush)) .flatMapSequential(buffer -> { Flux<ByteBuffer> progressData = ProgressReporter.addParallelProgressReporting(Flux.just(buffer), progressReceiver, progressLock, totalProgress); final String blockId = Base64.getEncoder().encodeToString( UUID.randomUUID().toString().getBytes(UTF_8)); return getBlockBlobAsyncClient().stageBlockWithResponse(blockId, progressData, buffer.remaining(), accessConditionsFinal.getLeaseAccessConditions()) .map(x -> blockId) .doFinally(x -> pool.returnBuffer(buffer)) .flux(); }) .collect(Collectors.toList()) .flatMap(ids -> getBlockBlobAsyncClient().commitBlockListWithResponse(ids, headers, metadata, tier, accessConditions)); }