public virtual Stream OpenRead()

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));
                }
            }
        }