in sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs [2975:3364]
public virtual Stream OpenRead(
#pragma warning restore AZC0015 // Unexpected client method return type.
BlobOpenReadOptions options,
CancellationToken cancellationToken = default)
=> OpenReadInternal(
options?.Position ?? 0,
options?.BufferSize,
options?.Conditions,
allowModifications: options?.AllowModifications ?? false,
transferValidationOverride: options?.TransferValidation,
async: false,
cancellationToken).EnsureCompleted();
/// <summary>
/// Opens a stream for reading from the blob. The stream will only download
/// the blob as the stream is read from.
/// </summary>
/// <param name="options">
/// Optional parameters.
/// </param>
/// <param name="cancellationToken">
/// Optional <see cref="CancellationToken"/> to propagate
/// notifications that the operation should be cancelled.
/// </param>
/// <returns>
/// Returns a stream that will download the blob as the stream
/// is read from.
/// </returns>
/// <remarks>
/// A <see cref="RequestFailedException"/> will be thrown if
/// a failure occurs.
/// If multiple failures occur, an <see cref="AggregateException"/> will be thrown,
/// containing each failure instance.
/// </remarks>
#pragma warning disable AZC0015 // Unexpected client method return type.
public virtual async Task<Stream> OpenReadAsync(
#pragma warning restore AZC0015 // Unexpected client method return type.
BlobOpenReadOptions options,
CancellationToken cancellationToken = default)
=> await OpenReadInternal(
options?.Position ?? 0,
options?.BufferSize,
options?.Conditions,
allowModifications: options?.AllowModifications ?? false,
transferValidationOverride: options?.TransferValidation,
async: true,
cancellationToken).ConfigureAwait(false);
/// <summary>
/// Opens a stream for reading from the blob. The stream will only download
/// the blob as the stream is read from.
/// </summary>
/// <param name="position">
/// The position within the blob to begin the stream.
/// Defaults to the beginning of the blob.
/// </param>
/// <param name="bufferSize">
/// The buffer size (in bytes) to use when the stream downloads parts
/// of the blob. Defaults to 1 MB.
/// </param>
/// <param name="conditions">
/// Optional <see cref="BlobRequestConditions"/> to add conditions on
/// the download of the blob.
/// </param>
/// <param name="cancellationToken">
/// Optional <see cref="CancellationToken"/> to propagate
/// notifications that the operation should be cancelled.
/// </param>
/// <returns>
/// Returns a stream that will download the blob as the stream
/// is read from.
/// </returns>
/// <remarks>
/// A <see cref="RequestFailedException"/> will be thrown if
/// a failure occurs.
/// If multiple failures occur, an <see cref="AggregateException"/> will be thrown,
/// containing each failure instance.
/// </remarks>
[EditorBrowsable(EditorBrowsableState.Never)]
#pragma warning disable AZC0015 // Unexpected client method return type.
public virtual Stream OpenRead(
#pragma warning restore AZC0015 // Unexpected client method return type.
long position = 0,
int? bufferSize = default,
BlobRequestConditions conditions = default,
CancellationToken cancellationToken = default)
=> OpenReadInternal(
position,
bufferSize,
conditions,
allowModifications: false,
transferValidationOverride: default,
async: false,
cancellationToken).EnsureCompleted();
/// <summary>
/// Opens a stream for reading from the blob. The stream will only download
/// the blob as the stream is read from.
/// </summary>
/// <param name="allowBlobModifications">
/// If true, you can continue streaming a blob even if it has been modified.
/// </param>
/// <param name="position">
/// The position within the blob to begin the stream.
/// Defaults to the beginning of the blob.
/// </param>
/// <param name="bufferSize">
/// The buffer size (in bytes) to use when the stream downloads parts
/// of the blob. Defaults to 1 MB.
/// </param>
/// <param name="cancellationToken">
/// Optional <see cref="CancellationToken"/> to propagate
/// notifications that the operation should be cancelled.
/// </param>
/// <returns>
/// Returns a stream that will download the blob as the stream
/// is read from.
/// </returns>
/// <remarks>
/// A <see cref="RequestFailedException"/> will be thrown if
/// a failure occurs.
/// If multiple failures occur, an <see cref="AggregateException"/> will be thrown,
/// containing each failure instance.
/// </remarks>
[EditorBrowsable(EditorBrowsableState.Never)]
#pragma warning disable AZC0015 // Unexpected client method return type.
public virtual Stream OpenRead(
#pragma warning restore AZC0015 // Unexpected client method return type.
bool allowBlobModifications,
long position = 0,
int? bufferSize = default,
CancellationToken cancellationToken = default)
=> OpenReadInternal(
position: position,
bufferSize: bufferSize,
conditions: allowBlobModifications ? new BlobRequestConditions() : null,
allowModifications: allowBlobModifications,
transferValidationOverride: default,
async: false,
cancellationToken: cancellationToken).EnsureCompleted();
/// <summary>
/// Opens a stream for reading from the blob. The stream will only download
/// the blob as the stream is read from.
/// </summary>
/// <param name="position">
/// The position within the blob to begin the stream.
/// Defaults to the beginning of the blob.
/// </param>
/// <param name="bufferSize">
/// The buffer size (in bytes) to use when the stream downloads parts
/// of the blob. Defaults to 1 MB.
/// </param>
/// <param name="conditions">
/// Optional <see cref="BlobRequestConditions"/> to add conditions on
/// the download of the blob.
/// </param>
/// <param name="cancellationToken">
/// Optional <see cref="CancellationToken"/> to propagate
/// notifications that the operation should be cancelled.
/// </param>
/// <returns>
/// Returns a stream that will download the blob as the stream
/// is read from.
/// </returns>
/// <remarks>
/// A <see cref="RequestFailedException"/> will be thrown if
/// a failure occurs.
/// If multiple failures occur, an <see cref="AggregateException"/> will be thrown,
/// containing each failure instance.
/// </remarks>
[EditorBrowsable(EditorBrowsableState.Never)]
#pragma warning disable AZC0015 // Unexpected client method return type.
public virtual async Task<Stream> OpenReadAsync(
#pragma warning restore AZC0015 // Unexpected client method return type.
long position = 0,
int? bufferSize = default,
BlobRequestConditions conditions = default,
CancellationToken cancellationToken = default)
=> await OpenReadInternal(
position,
bufferSize,
conditions,
allowModifications: false,
transferValidationOverride: default,
async: true,
cancellationToken).ConfigureAwait(false);
/// <summary>
/// Opens a stream for reading from the blob. The stream will only download
/// the blob as the stream is read from.
/// </summary>
/// <param name="allowBlobModifications">
/// If true, you can continue streaming a blob even if it has been modified.
/// </param>
/// <param name="position">
/// The position within the blob to begin the stream.
/// Defaults to the beginning of the blob.
/// </param>
/// <param name="bufferSize">
/// The buffer size (in bytes) to use when the stream downloads parts
/// of the blob. Defaults to 1 MB.
/// </param>
/// <param name="cancellationToken">
/// Optional <see cref="CancellationToken"/> to propagate
/// notifications that the operation should be cancelled.
/// </param>
/// <returns>
/// Returns a stream that will download the blob as the stream
/// is read from.
/// </returns>
/// <remarks>
/// A <see cref="RequestFailedException"/> will be thrown if
/// a failure occurs.
/// If multiple failures occur, an <see cref="AggregateException"/> will be thrown,
/// containing each failure instance.
/// </remarks>
[EditorBrowsable(EditorBrowsableState.Never)]
#pragma warning disable AZC0015 // Unexpected client method return type.
public virtual async Task<Stream> OpenReadAsync(
#pragma warning restore AZC0015 // Unexpected client method return type.
bool allowBlobModifications,
long position = 0,
int? bufferSize = default,
CancellationToken cancellationToken = default)
=> await OpenReadInternal(
position: position,
bufferSize: bufferSize,
conditions: allowBlobModifications ? new BlobRequestConditions() : null,
allowModifications: allowBlobModifications,
transferValidationOverride: default,
async: true,
cancellationToken: cancellationToken).ConfigureAwait(false);
/// <summary>
/// Opens a stream for reading from the blob. The stream will only download
/// the blob as the stream is read from.
/// </summary>
/// <param name="position">
/// The position within the blob to begin the stream.
/// Defaults to the beginning of the blob.
/// </param>
/// <param name="bufferSize">
/// The buffer size (in bytes) to use when the stream downloads parts
/// of the blob. Defaults to 1 MB.
/// </param>
/// <param name="conditions">
/// Optional <see cref="BlobRequestConditions"/> to add conditions on
/// the download of the blob.
/// </param>
/// <param name="allowModifications">
/// Whether to allow modifications during the read.
/// </param>
/// <param name="transferValidationOverride">
/// Optional override for settings in the client options.
/// </param>
/// <param name="async">
/// Whether to invoke the operation asynchronously.
/// </param>
/// <param name="cancellationToken">
/// Optional <see cref="CancellationToken"/> to propagate
/// notifications that the operation should be cancelled.
/// </param>
/// <returns>
/// Returns a stream that will download the blob as the stream
/// is read from.
/// </returns>
/// <remarks>
/// A <see cref="RequestFailedException"/> will be thrown if
/// a failure occurs.
/// If multiple failures occur, an <see cref="AggregateException"/> will be thrown,
/// containing each failure instance.
/// </remarks>
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
internal async Task<Stream> OpenReadInternal(
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
long position,
int? bufferSize,
BlobRequestConditions conditions,
bool allowModifications,
DownloadTransferValidationOptions transferValidationOverride,
#pragma warning disable CA1801
bool async,
CancellationToken cancellationToken)
#pragma warning restore CA1801
{
DownloadTransferValidationOptions validationOptions = transferValidationOverride ?? _clientConfiguration.TransferValidation.Download;
using (ClientConfiguration.Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
{
ClientConfiguration.Pipeline.LogMethodEnter(
nameof(BlobBaseClient),
message:
$"{nameof(position)}: {position}\n" +
$"{nameof(bufferSize)}: {bufferSize}\n" +
$"{nameof(conditions)}: {conditions}");
string operationName = $"{nameof(BlobBaseClient)}.{nameof(OpenRead)}";
DiagnosticScope scope = ClientConfiguration.ClientDiagnostics.CreateScope(operationName);
try
{
scope.Start();
// This also makes sure that we fail fast if file doesn't exist.
Response<BlobProperties> blobProperties = await GetPropertiesInternal(
conditions: conditions,
async,
new RequestContext() { CancellationToken = cancellationToken }).ConfigureAwait(false);
ETag etag = blobProperties.Value.ETag;
var readConditions = conditions;
if (!allowModifications)
{
readConditions = readConditions?.WithIfMatch(etag) ?? new BlobRequestConditions { IfMatch = etag };
}
long blobContentLength = blobProperties.Value.ContentLength;
ClientSideDecryptor.ContentEncryptionKeyCache contentEncryptionKeyCache = default;
EncryptionData encryptionData = null;
if (UsingClientSideEncryption && !allowModifications)
{
contentEncryptionKeyCache = new();
encryptionData = BlobClientSideDecryptor.GetAndValidateEncryptionDataOrDefault(blobProperties?.Value?.Metadata);
}
LazyLoadingReadOnlyStream<BlobProperties>.PredictEncryptedRangeAdjustment rangeAdjustmentFunc = UsingClientSideEncryption
? r => BlobClientSideDecryptor.GetEncryptedBlobRange(r, encryptionData)
: LazyLoadingReadOnlyStream<BlobProperties>.NoRangeAdjustment;
return new LazyLoadingReadOnlyStream<BlobProperties>(
async (HttpRange range,
DownloadTransferValidationOptions downloadValidationOptions,
bool async,
CancellationToken cancellationToken) =>
{
HttpRange requestedRange = range;
if (UsingClientSideEncryption)
{
ClientSideDecryptor.BeginContentEncryptionKeyCaching(contentEncryptionKeyCache);
range = rangeAdjustmentFunc(requestedRange);
}
Response<BlobDownloadStreamingResult> response = await DownloadStreamingInternal(
range,
readConditions,
transferValidationOverride: downloadValidationOptions,
progressHandler: default,
operationName,
async,
cancellationToken).ConfigureAwait(false);
if (UsingClientSideEncryption)
{
response.Value.Content = await new BlobClientSideDecryptor(
new ClientSideDecryptor(ClientSideEncryption)).DecryptInternal(
response.Value.Content,
response.Value.Details.Metadata,
requestedRange,
response.Value.Details.ContentRange,
async,
cancellationToken).ConfigureAwait(false);
}
return Response.FromValue(
(IDownloadedContent)response.Value,
response.GetRawResponse());
},
async (bool async, CancellationToken cancellationToken)
=> await GetPropertiesInternal(
conditions: default,
async,
new RequestContext() { CancellationToken = cancellationToken }).ConfigureAwait(false),
validationOptions,
allowModifications,
blobContentLength,
position,
bufferSize,
rangeAdjustmentFunc);
}
catch (Exception ex)
{
scope.Failed(ex);
ClientConfiguration.Pipeline.LogException(ex);
throw;
}
finally
{
scope.Dispose();
ClientConfiguration.Pipeline.LogMethodExit(nameof(BlobContainerClient));
}
}
}