Source:
public static Flux<ByteBuffer> convertStreamToByteBuffer(InputStream data, long length, int blockSize) { final long[] currentTotalLength = new long[1]; return Flux.range(0, (int) Math.ceil((double) length / (double) blockSize)) .map(i -> i * blockSize) .concatMap(pos -> Mono.fromCallable(() -> { long count = pos + blockSize > length ? length - pos : blockSize; byte[] cache = new byte[(int) count]; int numOfBytes = 0; int offset = 0; int len = (int) count; while (numOfBytes != -1 && offset < count) { numOfBytes = data.read(cache, offset, len); offset += numOfBytes; len -= numOfBytes; if (numOfBytes != -1) { currentTotalLength[0] += numOfBytes; } } if (numOfBytes == -1 && currentTotalLength[0] < length) { throw LOGGER.logExceptionAsError(new UnexpectedLengthException( String.format("Request body emitted %d bytes, less than the expected %d bytes.", currentTotalLength[0], length), currentTotalLength[0], length)); } return ByteBuffer.wrap(cache); })) .doOnComplete(() -> { try { if (data.available() > 0) { long totalLength = currentTotalLength[0] + data.available(); throw LOGGER.logExceptionAsError(new UnexpectedLengthException( String.format("Request body emitted %d bytes, more than the expected %d bytes.", totalLength, length), totalLength, length)); } } catch (IOException e) { throw LOGGER.logExceptionAsError(new RuntimeException("I/O errors occurs. Error details: " + e.getMessage())); } }) .doFirst(() -> { currentTotalLength[0] = 0; try { data.reset(); } catch (IOException e) { throw LOGGER.logExceptionAsError(new RuntimeException(e)); } }); }

Target:
public static Flux<ByteBuffer> convertStreamToByteBuffer(InputStream data, long length, int blockSize) { data.mark(Integer.MAX_VALUE); return Flux.defer(() -> { final long[] currentTotalLength = new long[1]; try { data.reset(); } catch (IOException e) { throw LOGGER.logExceptionAsError(new RuntimeException(e)); } return Flux.range(0, (int) Math.ceil((double) length / (double) blockSize)) .map(i -> i * blockSize) .concatMap(pos -> Mono.fromCallable(() -> { long count = pos + blockSize > length ? length - pos : blockSize; byte[] cache = new byte[(int) count]; int numOfBytes = 0; int offset = 0; int len = (int) count; while (numOfBytes != -1 && offset < count) { numOfBytes = data.read(cache, offset, len); offset += numOfBytes; len -= numOfBytes; if (numOfBytes != -1) { currentTotalLength[0] += numOfBytes; } } if (numOfBytes == -1 && currentTotalLength[0] < length) { throw LOGGER.logExceptionAsError(new UnexpectedLengthException( String.format("Request body emitted %d bytes, less than the expected %d bytes.", currentTotalLength[0], length), currentTotalLength[0], length)); } return ByteBuffer.wrap(cache); })) .doOnComplete(() -> { try { if (data.available() > 0) { long totalLength = currentTotalLength[0] + data.available(); throw LOGGER.logExceptionAsError(new UnexpectedLengthException( String.format("Request body emitted %d bytes, more than the expected %d bytes.", totalLength, length), totalLength, length)); } else if (currentTotalLength[0] > length) { throw LOGGER.logExceptionAsError(new IllegalStateException( String.format("Read more data than was requested. Size of data read: %d. Size of data" + " requested: %d", currentTotalLength[0], length))); } } catch (IOException e) { throw LOGGER.logExceptionAsError(new RuntimeException("I/O errors occurs. Error details: " + e.getMessage())); } }); }); }