@@ -1407,9 +1407,12 @@ Mono<BlobDownloadAsyncResponse> downloadStreamWithResponse(BlobRange range, Down
14071407 // MD5 validation is enabled if:
14081408 // 1. getRangeContentMd5 is explicitly true, OR
14091409 // 2. contentValidationOptions.isMd5ValidationEnabled() is true
1410- Boolean getMD5 = null ;
1410+ // Make this effectively final for lambda usage
1411+ final Boolean finalGetMD5 ;
14111412 if (getRangeContentMd5 || (contentValidationOptions != null && contentValidationOptions .isMd5ValidationEnabled ())) {
1412- getMD5 = true ;
1413+ finalGetMD5 = true ;
1414+ } else {
1415+ finalGetMD5 = null ;
14131416 }
14141417
14151418 BlobRequestConditions finalRequestConditions
@@ -1421,7 +1424,7 @@ Mono<BlobDownloadAsyncResponse> downloadStreamWithResponse(BlobRange range, Down
14211424 ? new Context ("azure-eagerly-convert-headers" , true )
14221425 : context .addData ("azure-eagerly-convert-headers" , true );
14231426
1424- return downloadRange (finalRange , finalRequestConditions , finalRequestConditions .getIfMatch (), getMD5 ,
1427+ return downloadRange (finalRange , finalRequestConditions , finalRequestConditions .getIfMatch (), finalGetMD5 ,
14251428 firstRangeContext ).map (response -> {
14261429 BlobsDownloadHeaders blobsDownloadHeaders = new BlobsDownloadHeaders (response .getHeaders ());
14271430 String eTag = blobsDownloadHeaders .getETag ();
@@ -1473,17 +1476,51 @@ Mono<BlobDownloadAsyncResponse> downloadStreamWithResponse(BlobRange range, Down
14731476
14741477 try {
14751478 return downloadRange (new BlobRange (initialOffset + offset , newCount ), finalRequestConditions ,
1476- eTag , getMD5 , context );
1479+ eTag , finalGetMD5 , context );
14771480 } catch (Exception e ) {
14781481 return Mono .error (e );
14791482 }
14801483 };
14811484
1482- // Create a new response with the processed stream (which may include structured message decoding)
1483- // Use the same approach as the original method to maintain consistency
1484- return BlobDownloadAsyncResponseConstructorProxy .create (
1485- new ResponseBase <>(response .getRequest (), response .getStatusCode (), response .getHeaders (),
1486- processedStream , blobDownloadHeaders ), onDownloadErrorResume , finalOptions );
1485+ // Apply structured message decoding if enabled - this allows both MD5 and structured message to coexist
1486+ if (contentValidationOptions != null && contentValidationOptions .isStructuredMessageValidationEnabled ()) {
1487+ // Use the content length from headers to determine expected length for structured message decoding
1488+ Long contentLength = blobDownloadHeaders .getContentLength ();
1489+ Flux <ByteBuffer > processedStream = StructuredMessageDecodingStream .wrapStreamIfNeeded (response .getValue (), contentLength , contentValidationOptions );
1490+
1491+ // Create a new StreamResponse with the processed stream
1492+ StreamResponse processedResponse = new StreamResponse () {
1493+ @ Override
1494+ public int getStatusCode () {
1495+ return response .getStatusCode ();
1496+ }
1497+
1498+ @ Override
1499+ public HttpHeaders getHeaders () {
1500+ return response .getHeaders ();
1501+ }
1502+
1503+ @ Override
1504+ public Flux <ByteBuffer > getValue () {
1505+ return processedStream ;
1506+ }
1507+
1508+ @ Override
1509+ public HttpRequest getRequest () {
1510+ return response .getRequest ();
1511+ }
1512+
1513+ @ Override
1514+ public void close () {
1515+ response .close ();
1516+ }
1517+ };
1518+
1519+ return BlobDownloadAsyncResponseConstructorProxy .create (processedResponse , onDownloadErrorResume , finalOptions );
1520+ } else {
1521+ // No structured message processing needed, use original response
1522+ return BlobDownloadAsyncResponseConstructorProxy .create (response , onDownloadErrorResume , finalOptions );
1523+ }
14871524 });
14881525 }
14891526
0 commit comments