Skip to content

Commit b38a9c2

Browse files
authored
[Storage] [BUG] Fixed ContentRange is null in BlobDownloadDetails when calling DownloadStreamingAsync with HttpRange "0-" (Azure#48272)
* Initial commit * initial commit * initial commit * Exported Api * changed _isRangeSet to internal * undo export api * fixed SetupDownload * re-recorded old tests * re-record pt2 * re-recorded pt 3 * re-record pt4 * typo
1 parent 88e339a commit b38a9c2

File tree

8 files changed

+177
-19
lines changed

8 files changed

+177
-19
lines changed

sdk/storage/Azure.Storage.Blobs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
### Breaking Changes
88

99
### Bugs Fixed
10+
- Fixed ContentRange is null in BlobDownloadDetails when calling DownloadStreamingAsync with HttpRange "0-" #47882
1011

1112
### Other Changes
1213

sdk/storage/Azure.Storage.Blobs/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "net",
44
"TagPrefix": "net/storage/Azure.Storage.Blobs",
5-
"Tag": "net/storage/Azure.Storage.Blobs_f174db6035"
5+
"Tag": "net/storage/Azure.Storage.Blobs_11b2adbc87"
66
}

sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,7 @@ private async Task<Response<BlobDownloadInfo>> DownloadInternal(
10071007
{
10081008
Response<BlobDownloadStreamingResult> response = await DownloadStreamingDirect(
10091009
range,
1010+
range != default,
10101011
conditions,
10111012
rangeGetContentHash.ToValidationOptions(),
10121013
progressHandler: default,
@@ -1240,6 +1241,7 @@ public virtual Response<BlobDownloadStreamingResult> DownloadStreaming(
12401241
{
12411242
return DownloadStreamingDirect(
12421243
range,
1244+
true,
12431245
conditions,
12441246
rangeGetContentHash.ToValidationOptions(),
12451247
progressHandler,
@@ -1316,6 +1318,7 @@ public virtual async Task<Response<BlobDownloadStreamingResult>> DownloadStreami
13161318
{
13171319
return await DownloadStreamingDirect(
13181320
range,
1321+
true,
13191322
conditions,
13201323
rangeGetContentHash.ToValidationOptions(),
13211324
progressHandler,
@@ -1369,6 +1372,7 @@ public virtual Response<BlobDownloadStreamingResult> DownloadStreaming(
13691372
{
13701373
return DownloadStreamingDirect(
13711374
options?.Range ?? default,
1375+
options?._isRangeSet ?? false,
13721376
options?.Conditions,
13731377
options?.TransferValidation,
13741378
options?.ProgressHandler,
@@ -1416,6 +1420,7 @@ public virtual async Task<Response<BlobDownloadStreamingResult>> DownloadStreami
14161420
{
14171421
return await DownloadStreamingDirect(
14181422
options?.Range ?? default,
1423+
options?._isRangeSet ?? false,
14191424
options?.Conditions,
14201425
options?.TransferValidation,
14211426
options?.ProgressHandler,
@@ -1430,6 +1435,7 @@ public virtual async Task<Response<BlobDownloadStreamingResult>> DownloadStreami
14301435
/// Implementation for public DownloadStreaming/DownloadContent methods to call into.
14311436
/// </summary>
14321437
/// <param name="range"></param>
1438+
/// <param name="isRangeSet"></param>
14331439
/// <param name="conditions"></param>
14341440
/// <param name="transferValidationOverride"></param>
14351441
/// <param name="progressHandler"></param>
@@ -1439,6 +1445,7 @@ public virtual async Task<Response<BlobDownloadStreamingResult>> DownloadStreami
14391445
/// <returns></returns>
14401446
private async ValueTask<Response<BlobDownloadStreamingResult>> DownloadStreamingDirect(
14411447
HttpRange range,
1448+
bool isRangeSet,
14421449
BlobRequestConditions conditions,
14431450
DownloadTransferValidationOptions transferValidationOverride,
14441451
IProgress<long> progressHandler,
@@ -1455,7 +1462,7 @@ private async ValueTask<Response<BlobDownloadStreamingResult>> DownloadStreaming
14551462
}
14561463
}
14571464

1458-
var response = await DownloadStreamingInternal(range, conditions, transferValidationOverride, progressHandler, operationName, async, cancellationToken).ConfigureAwait(false);
1465+
var response = await DownloadStreamingInternal(range, isRangeSet, conditions, transferValidationOverride, progressHandler, operationName, async, cancellationToken).ConfigureAwait(false);
14591466

14601467
// if using clientside encryption, wrap the auto-retry stream in a decryptor
14611468
// we already return a nonseekable stream; returning a crypto stream is fine
@@ -1481,6 +1488,9 @@ private async ValueTask<Response<BlobDownloadStreamingResult>> DownloadStreaming
14811488
/// <param name="range">
14821489
/// Optionally specified range.
14831490
/// </param>
1491+
/// <param name="isRangeSet">
1492+
/// If range has been set
1493+
/// </param>
14841494
/// <param name="conditions">
14851495
/// Access conditions.
14861496
/// </param>
@@ -1502,6 +1512,7 @@ private async ValueTask<Response<BlobDownloadStreamingResult>> DownloadStreaming
15021512
/// <returns></returns>
15031513
internal virtual async ValueTask<Response<BlobDownloadStreamingResult>> DownloadStreamingInternal(
15041514
HttpRange range,
1515+
bool isRangeSet,
15051516
BlobRequestConditions conditions,
15061517
DownloadTransferValidationOptions transferValidationOverride,
15071518
IProgress<long> progressHandler,
@@ -1529,6 +1540,7 @@ internal virtual async ValueTask<Response<BlobDownloadStreamingResult>> Download
15291540
// Start downloading the blob
15301541
Response<BlobDownloadStreamingResult> response = await StartDownloadAsync(
15311542
range,
1543+
isRangeSet,
15321544
conditions,
15331545
validationOptions,
15341546
async: async,
@@ -1552,6 +1564,7 @@ internal virtual async ValueTask<Response<BlobDownloadStreamingResult>> Download
15521564
startOffset =>
15531565
StartDownloadAsync(
15541566
range,
1567+
isRangeSet,
15551568
conditionsWithEtag,
15561569
validationOptions,
15571570
startOffset,
@@ -1562,6 +1575,7 @@ internal virtual async ValueTask<Response<BlobDownloadStreamingResult>> Download
15621575
async startOffset =>
15631576
(await StartDownloadAsync(
15641577
range,
1578+
isRangeSet,
15651579
conditionsWithEtag,
15661580
validationOptions,
15671581
startOffset,
@@ -1629,6 +1643,9 @@ await ContentHasher.AssertResponseHashMatchInternal(
16291643
/// If provided, only download the bytes of the blob in the specified
16301644
/// range. If not provided, download the entire blob.
16311645
/// </param>
1646+
/// <param name="isRangeSet">
1647+
/// Whether range has been set.
1648+
/// </param>
16321649
/// <param name="conditions">
16331650
/// Optional <see cref="BlobRequestConditions"/> to add conditions on
16341651
/// downloading this blob.
@@ -1659,14 +1676,15 @@ await ContentHasher.AssertResponseHashMatchInternal(
16591676
/// </remarks>
16601677
private async ValueTask<Response<BlobDownloadStreamingResult>> StartDownloadAsync(
16611678
HttpRange range,
1679+
bool isRangeSet,
16621680
BlobRequestConditions conditions,
16631681
DownloadTransferValidationOptions validationOptions,
16641682
long startOffset = 0,
16651683
bool async = true,
16661684
CancellationToken cancellationToken = default)
16671685
{
16681686
HttpRange? pageRange = null;
1669-
if (range != default(HttpRange)) // we want to check between non-nullable ranges
1687+
if (isRangeSet) // we want to check if the range has been manually set
16701688
{
16711689
pageRange = new HttpRange(
16721690
range.Offset + startOffset,
@@ -1943,6 +1961,7 @@ public virtual Response<BlobDownloadResult> DownloadContent(
19431961
conditions,
19441962
progressHandler: default,
19451963
range: default,
1964+
isRangeSet: false,
19461965
transferValidationOverride: default,
19471966
false, // async
19481967
cancellationToken)
@@ -1999,6 +2018,7 @@ await DownloadContentInternal(
19992018
conditions,
20002019
progressHandler: default,
20012020
range: default,
2021+
isRangeSet: false,
20022022
transferValidationOverride: default,
20032023
true, // async
20042024
cancellationToken)
@@ -2064,6 +2084,7 @@ public virtual Response<BlobDownloadResult> DownloadContent(
20642084
conditions,
20652085
progressHandler,
20662086
range,
2087+
true,
20672088
transferValidationOverride: default,
20682089
false, // async
20692090
cancellationToken)
@@ -2129,6 +2150,7 @@ await DownloadContentInternal(
21292150
conditions,
21302151
progressHandler,
21312152
range,
2153+
true,
21322154
transferValidationOverride: default,
21332155
true, // async
21342156
cancellationToken)
@@ -2181,6 +2203,7 @@ public virtual Response<BlobDownloadResult> DownloadContent(
21812203
options?.Conditions,
21822204
options?.ProgressHandler,
21832205
options?.Range ?? default,
2206+
options?._isRangeSet ?? false,
21842207
options?.TransferValidation,
21852208
async: false,
21862209
cancellationToken).EnsureCompleted();
@@ -2232,6 +2255,7 @@ await DownloadContentInternal(
22322255
options?.Conditions,
22332256
options?.ProgressHandler,
22342257
options?.Range ?? default,
2258+
options?._isRangeSet ?? false,
22352259
options?.TransferValidation,
22362260
async: true,
22372261
cancellationToken).ConfigureAwait(false);
@@ -2240,12 +2264,14 @@ private async Task<Response<BlobDownloadResult>> DownloadContentInternal(
22402264
BlobRequestConditions conditions,
22412265
IProgress<long> progressHandler,
22422266
HttpRange range,
2267+
bool isRangeSet,
22432268
DownloadTransferValidationOptions transferValidationOverride,
22442269
bool async,
22452270
CancellationToken cancellationToken)
22462271
{
22472272
Response<BlobDownloadStreamingResult> response = await DownloadStreamingDirect(
22482273
range,
2274+
isRangeSet,
22492275
conditions,
22502276
transferValidationOverride: transferValidationOverride,
22512277
progressHandler,
@@ -3186,6 +3212,7 @@ internal async Task<Stream> OpenReadInternal(
31863212
}
31873213
Response<BlobDownloadStreamingResult> response = await DownloadStreamingInternal(
31883214
range,
3215+
true,
31893216
readConditions,
31903217
transferValidationOverride: downloadValidationOptions,
31913218
progressHandler: default,

sdk/storage/Azure.Storage.Blobs/src/Models/BlobDownloadOptions.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,22 @@ namespace Azure.Storage.Blobs.Models
1111
/// </summary>
1212
public class BlobDownloadOptions
1313
{
14+
private HttpRange _range;
15+
internal bool _isRangeSet;
16+
1417
/// <summary>
1518
/// If provided, only download the bytes of the blob in the specified
1619
/// range. If not provided, download the entire blob.
1720
/// </summary>
18-
public HttpRange Range { get; set; }
21+
public HttpRange Range
22+
{
23+
get => _range;
24+
set
25+
{
26+
_range = value;
27+
_isRangeSet = true;
28+
}
29+
}
1930

2031
/// <summary>
2132
/// Optional <see cref="BlobRequestConditions"/> to add conditions on

sdk/storage/Azure.Storage.Blobs/src/PartitionedDownloader.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ public async Task<Response> DownloadToInternal(
161161
{
162162
initialResponse = await _client.DownloadStreamingInternal(
163163
initialRange,
164+
true,
164165
conditions,
165166
ValidationOptions,
166167
_progress,
@@ -172,6 +173,7 @@ public async Task<Response> DownloadToInternal(
172173
{
173174
initialResponse = await _client.DownloadStreamingInternal(
174175
range: default,
176+
false,
175177
conditions,
176178
ValidationOptions,
177179
_progress,
@@ -230,8 +232,8 @@ await HandleOneShotDownload(initialResponse, destination, async, cancellationTok
230232
BlobRequestConditions conditionsWithEtag = conditions?.WithIfMatch(etag) ?? new BlobRequestConditions { IfMatch = etag };
231233

232234
#pragma warning disable AZC0110 // DO NOT use await keyword in possibly synchronous scope.
233-
// Rule checker cannot understand this section, but this
234-
// massively reduces code duplication.
235+
// Rule checker cannot understand this section, but this
236+
// massively reduces code duplication.
235237
int effectiveWorkerCount = async ? _maxWorkerCount : 1;
236238
if (effectiveWorkerCount > 1)
237239
{
@@ -260,6 +262,7 @@ await HandleOneShotDownload(initialResponse, destination, async, cancellationTok
260262
ValueTask<Response<BlobDownloadStreamingResult>> responseValueTask = _client
261263
.DownloadStreamingInternal(
262264
httpRange,
265+
true,
263266
conditionsWithEtag,
264267
ValidationOptions,
265268
_progress,
@@ -338,13 +341,13 @@ await CopyToInternal(
338341
async,
339342
cancellationToken)
340343
.ConfigureAwait(false);
341-
if (UseMasterCrc)
342-
{
343-
StorageCrc64Composer.Compose(
344-
(composedCrc.ToArray(), 0L),
345-
(partitionChecksum.ToArray(), response.Value.Details.ContentLength)
346-
).CopyTo(composedCrc);
347-
}
344+
if (UseMasterCrc)
345+
{
346+
StorageCrc64Composer.Compose(
347+
(composedCrc.ToArray(), 0L),
348+
(partitionChecksum.ToArray(), response.Value.Details.ContentLength)
349+
).CopyTo(composedCrc);
350+
}
348351
}
349352
}
350353
}

0 commit comments

Comments
 (0)