< Summary

Class:Azure.Storage.Blobs.Specialized.BlobBaseClient
Assembly:Azure.Storage.Blobs
File(s):C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs\src\BlobBaseClient.cs
Covered lines:826
Uncovered lines:24
Coverable lines:850
Total lines:4079
Line coverage:97.1% (826 of 850)
Covered branches:232
Total branches:260
Branch coverage:89.2% (232 of 260)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
get_Uri()-100%100%
get_Pipeline()-100%100%
get_Version()-100%100%
get_ClientDiagnostics()-100%100%
get_CustomerProvidedKey()-100%100%
get_ClientSideEncryption()-100%100%
get_UsingClientSideEncryption()-100%100%
get_EncryptionScope()-100%100%
get_AccountName()-100%100%
get_BlobContainerName()-100%100%
get_Name()-100%100%
.ctor()-100%100%
.ctor(...)-100%100%
.ctor(...)-100%75%
.ctor(...)-100%100%
.ctor(...)-100%100%
.ctor(...)-100%100%
.ctor(...)-100%75%
.ctor(...)-100%50%
WithSnapshot(...)-100%100%
WithSnapshotCore(...)-100%100%
WithVersion(...)-100%100%
WithVersionCore(...)-100%100%
SetNameFieldsIfNull()-100%100%
Download()-100%100%
DownloadAsync()-100%100%
Download(...)-100%100%
DownloadAsync()-100%100%
Download(...)-100%100%
DownloadAsync()-100%100%
DownloadInternal()-53.33%66.67%
<DownloadInternal()-0%100%
StartDownloadAsync()-100%96.67%
DownloadTo(...)-100%100%
DownloadTo(...)-100%100%
DownloadToAsync()-100%100%
DownloadToAsync()-100%100%
DownloadTo(...)-100%100%
DownloadTo(...)-100%100%
DownloadToAsync()-100%100%
DownloadToAsync()-100%100%
DownloadTo(...)-100%100%
DownloadTo(...)-100%100%
DownloadToAsync()-100%100%
DownloadToAsync()-100%100%
StagedDownloadAsync()-100%100%
OpenRead(...)-100%100%
OpenRead(...)-100%50%
OpenReadAsync()-100%100%
OpenReadAsync()-100%50%
OpenReadInternal()-90.63%100%
StartCopyFromUri(...)-100%50%
StartCopyFromUri(...)-100%100%
StartCopyFromUriAsync()-100%50%
StartCopyFromUriAsync()-100%100%
StartCopyFromUriInternal()-100%100%
AbortCopyFromUri(...)-100%100%
AbortCopyFromUriAsync()-100%100%
AbortCopyFromUriInternal()-100%100%
SyncCopyFromUri(...)-100%100%
SyncCopyFromUriAsync()-100%100%
SyncCopyFromUriInternal()-100%100%
Delete(...)-100%100%
DeleteAsync()-100%100%
DeleteIfExists(...)-100%100%
DeleteIfExistsAsync()-100%100%
DeleteIfExistsInternal()-100%100%
DeleteInternal()-100%100%
Exists(...)-100%100%
ExistsAsync()-100%100%
ExistsInternal()-100%100%
Undelete(...)-100%100%
UndeleteAsync()-100%100%
UndeleteInternal()-100%100%
GetProperties(...)-100%100%
GetPropertiesAsync()-100%100%
GetPropertiesInternal()-100%100%
SetHttpHeaders(...)-100%100%
SetHttpHeadersAsync()-100%100%
SetHttpHeadersInternal()-100%75%
SetMetadata(...)-100%100%
SetMetadataAsync()-100%100%
SetMetadataInternal()-100%100%
CreateSnapshot(...)-100%100%
CreateSnapshotAsync()-100%100%
CreateSnapshotInternal()-100%100%
SetAccessTier(...)-100%100%
SetAccessTierAsync()-100%100%
SetAccessTierInternal()-100%100%
GetTags(...)-100%100%
GetTagsAsync()-100%100%
GetTagsInternal()-100%100%
SetTags(...)-100%100%
SetTagsAsync()-100%100%
SetTagsInternal()-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs\src\BlobBaseClient.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.ComponentModel;
 6using System.Diagnostics;
 7using System.IO;
 8using System.Threading;
 9using System.Threading.Tasks;
 10using Azure.Core;
 11using Azure.Core.Pipeline;
 12using Azure.Storage.Blobs.Models;
 13using Azure.Storage.Cryptography;
 14using Azure.Storage.Shared;
 15using Metadata = System.Collections.Generic.IDictionary<string, string>;
 16using Tags = System.Collections.Generic.IDictionary<string, string>;
 17
 18#pragma warning disable SA1402  // File may only contain a single type
 19
 20namespace Azure.Storage.Blobs.Specialized
 21{
 22    /// <summary>
 23    /// The <see cref="BlobBaseClient"/> allows you to manipulate Azure Storage
 24    /// blobs.
 25    /// </summary>
 26    public class BlobBaseClient
 27    {
 28        /// <summary>
 29        /// The blob's primary <see cref="Uri"/> endpoint.
 30        /// </summary>
 31        private readonly Uri _uri;
 32
 33        /// <summary>
 34        /// Gets the blob's primary <see cref="Uri"/> endpoint.
 35        /// </summary>
 2143236        public virtual Uri Uri => _uri;
 37
 38        /// <summary>
 39        /// The <see cref="HttpPipeline"/> transport pipeline used to send
 40        /// every request.
 41        /// </summary>
 42        private readonly HttpPipeline _pipeline;
 43
 44        /// <summary>
 45        /// The <see cref="HttpPipeline"/> transport pipeline used to send
 46        /// every request.
 47        /// </summary>
 3461648        internal virtual HttpPipeline Pipeline => _pipeline;
 49
 50        /// <summary>
 51        /// The version of the service to use when sending requests.
 52        /// </summary>
 53        private readonly BlobClientOptions.ServiceVersion _version;
 54
 55        /// <summary>
 56        /// The version of the service to use when sending requests.
 57        /// </summary>
 1832458        internal virtual BlobClientOptions.ServiceVersion Version => _version;
 59
 60        /// <summary>
 61        /// The <see cref="ClientDiagnostics"/> instance used to create diagnostic scopes
 62        /// every request.
 63        /// </summary>
 64        private readonly ClientDiagnostics _clientDiagnostics;
 65
 66        /// <summary>
 67        /// The <see cref="ClientDiagnostics"/> instance used to create diagnostic scopes
 68        /// every request.
 69        /// </summary>
 1870070        internal virtual ClientDiagnostics ClientDiagnostics => _clientDiagnostics;
 71
 72        /// <summary>
 73        /// The <see cref="CustomerProvidedKey"/> to be used when sending requests.
 74        /// </summary>
 75        internal readonly CustomerProvidedKey? _customerProvidedKey;
 76
 77        /// <summary>
 78        /// The <see cref="CustomerProvidedKey"/> to be used when sending requests.
 79        /// </summary>
 3845280        internal virtual CustomerProvidedKey? CustomerProvidedKey => _customerProvidedKey;
 81
 82        /// <summary>
 83        /// The <see cref="ClientSideEncryptionOptions"/> to be used when sending/receiving requests.
 84        /// </summary>
 85        private readonly ClientSideEncryptionOptions _clientSideEncryption;
 86
 87        /// <summary>
 88        /// The <see cref="ClientSideEncryptionOptions"/> to be used when sending/receiving requests.
 89        /// </summary>
 465690        internal virtual ClientSideEncryptionOptions ClientSideEncryption => _clientSideEncryption;
 91
 450492        internal bool UsingClientSideEncryption => ClientSideEncryption != default;
 93
 94        /// <summary>
 95        /// The name of the Encryption Scope to be used when sending requests.
 96        /// </summary>
 97        internal readonly string _encryptionScope;
 98
 99        /// <summary>
 100        /// The name of the Encryption Scope to be used when sending requests.
 101        /// </summary>
 11836102        internal virtual string EncryptionScope => _encryptionScope;
 103
 104        /// <summary>
 105        /// The Storage account name corresponding to the blob client.
 106        /// </summary>
 107        private string _accountName;
 108
 109        /// <summary>
 110        /// Gets the Storage account name corresponding to the blob client.
 111        /// </summary>
 112        public virtual string AccountName
 113        {
 114            get
 115            {
 48116                SetNameFieldsIfNull();
 48117                return _accountName;
 118            }
 119        }
 120
 121        /// <summary>
 122        /// The container name corresponding to the blob client.
 123        /// </summary>
 124        private string _containerName;
 125
 126        /// <summary>
 127        /// Gets the container name corresponding to the blob client.
 128        /// </summary>
 129        public virtual string BlobContainerName
 130        {
 131            get
 132            {
 48133                SetNameFieldsIfNull();
 48134                return _containerName;
 135            }
 136        }
 137
 138        /// <summary>
 139        /// The name of the blob.
 140        /// </summary>
 141        private string _name;
 142
 143        /// <summary>
 144        /// Gets the name of the blob.
 145        /// </summary>
 146        public virtual string Name
 147        {
 148            get
 149            {
 264150                SetNameFieldsIfNull();
 264151                return _name;
 152            }
 153        }
 154
 155        #region ctors
 156        /// <summary>
 157        /// Initializes a new instance of the <see cref="BlobBaseClient"/>
 158        /// class.
 159        /// </summary>
 6372160        protected BlobBaseClient()
 161        {
 6372162        }
 163
 164        /// <summary>
 165        /// Initializes a new instance of the <see cref="BlobBaseClient"/>
 166        /// class.
 167        /// </summary>
 168        /// <param name="connectionString">
 169        /// A connection string includes the authentication information
 170        /// required for your application to access data in an Azure Storage
 171        /// account at runtime.
 172        ///
 173        /// For more information,
 174        /// <see href="https://docs.microsoft.com/azure/storage/common/storage-configure-connection-string">
 175        /// Configure Azure Storage connection strings</see>
 176        /// </param>
 177        /// <param name="blobContainerName">
 178        /// The name of the container containing this blob.
 179        /// </param>
 180        /// <param name="blobName">
 181        /// The name of this blob.
 182        /// </param>
 183        public BlobBaseClient(string connectionString, string blobContainerName, string blobName)
 8184            : this(connectionString, blobContainerName, blobName, null)
 185        {
 8186        }
 187
 188        /// <summary>
 189        /// Initializes a new instance of the <see cref="BlobBaseClient"/>
 190        /// class.
 191        /// </summary>
 192        /// <param name="connectionString">
 193        /// A connection string includes the authentication information
 194        /// required for your application to access data in an Azure Storage
 195        /// account at runtime.
 196        ///
 197        /// For more information,
 198        /// <see href="https://docs.microsoft.com/azure/storage/common/storage-configure-connection-string">
 199        /// Configure Azure Storage connection strings</see>
 200        /// </param>
 201        /// <param name="blobContainerName">
 202        /// The name of the container containing this blob.
 203        /// </param>
 204        /// <param name="blobName">
 205        /// The name of this blob.
 206        /// </param>
 207        /// <param name="options">
 208        /// Optional client options that define the transport pipeline
 209        /// policies for authentication, retries, etc., that are applied to
 210        /// every request.
 211        /// </param>
 112212        public BlobBaseClient(string connectionString, string blobContainerName, string blobName, BlobClientOptions opti
 213        {
 112214            options ??= new BlobClientOptions();
 112215            var conn = StorageConnectionString.Parse(connectionString);
 112216            var builder =
 112217                new BlobUriBuilder(conn.BlobEndpoint)
 112218                {
 112219                    BlobContainerName = blobContainerName,
 112220                    BlobName = blobName
 112221                };
 112222            _uri = builder.ToUri();
 112223            _pipeline = options.Build(conn.Credentials);
 112224            _version = options.Version;
 112225            _clientDiagnostics = new ClientDiagnostics(options);
 112226            _customerProvidedKey = options.CustomerProvidedKey;
 112227            _clientSideEncryption = options._clientSideEncryptionOptions?.Clone();
 112228            _encryptionScope = options.EncryptionScope;
 112229            BlobErrors.VerifyHttpsCustomerProvidedKey(_uri, _customerProvidedKey);
 112230            BlobErrors.VerifyCpkAndEncryptionScopeNotBothSet(_customerProvidedKey, _encryptionScope);
 112231        }
 232
 233        /// <summary>
 234        /// Initializes a new instance of the <see cref="BlobBaseClient"/>
 235        /// class.
 236        /// </summary>
 237        /// <param name="blobUri">
 238        /// A <see cref="Uri"/> referencing the blob that includes the
 239        /// name of the account, the name of the container, and the name of
 240        /// the blob.
 241        /// This is likely to be similar to "https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}".
 242        /// </param>
 243        /// <param name="options">
 244        /// Optional client options that define the transport pipeline
 245        /// policies for authentication, retries, etc., that are applied to
 246        /// every request.
 247        /// </param>
 248        public BlobBaseClient(Uri blobUri, BlobClientOptions options = default)
 268249            : this(blobUri, (HttpPipelinePolicy)null, options)
 250        {
 248251        }
 252
 253        /// <summary>
 254        /// Initializes a new instance of the <see cref="BlobBaseClient"/>
 255        /// class.
 256        /// </summary>
 257        /// <param name="blobUri">
 258        /// A <see cref="Uri"/> referencing the blob that includes the
 259        /// name of the account, the name of the container, and the name of
 260        /// the blob.
 261        /// This is likely to be similar to "https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}".
 262        /// </param>
 263        /// <param name="credential">
 264        /// The shared key credential used to sign requests.
 265        /// </param>
 266        /// <param name="options">
 267        /// Optional client options that define the transport pipeline
 268        /// policies for authentication, retries, etc., that are applied to
 269        /// every request.
 270        /// </param>
 271        public BlobBaseClient(Uri blobUri, StorageSharedKeyCredential credential, BlobClientOptions options = default)
 100272            : this(blobUri, credential.AsPolicy(), options)
 273        {
 100274        }
 275
 276        /// <summary>
 277        /// Initializes a new instance of the <see cref="BlobBaseClient"/>
 278        /// class.
 279        /// </summary>
 280        /// <param name="blobUri">
 281        /// A <see cref="Uri"/> referencing the blob that includes the
 282        /// name of the account, the name of the container, and the name of
 283        /// the blob.
 284        /// This is likely to be similar to "https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}".
 285        /// </param>
 286        /// <param name="credential">
 287        /// The token credential used to sign requests.
 288        /// </param>
 289        /// <param name="options">
 290        /// Optional client options that define the transport pipeline
 291        /// policies for authentication, retries, etc., that are applied to
 292        /// every request.
 293        /// </param>
 294        public BlobBaseClient(Uri blobUri, TokenCredential credential, BlobClientOptions options = default)
 24295            : this(blobUri, credential.AsPolicy(), options)
 296        {
 24297            Errors.VerifyHttpsTokenAuth(blobUri);
 4298        }
 299
 300        /// <summary>
 301        /// Initializes a new instance of the <see cref="BlobBaseClient"/>
 302        /// class.
 303        /// </summary>
 304        /// <param name="blobUri">
 305        /// A <see cref="Uri"/> referencing the blob that includes the
 306        /// name of the account, the name of the container, and the name of
 307        /// the blob.
 308        /// This is likely to be similar to "https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}".
 309        /// </param>
 310        /// <param name="authentication">
 311        /// An optional authentication policy used to sign requests.
 312        /// </param>
 313        /// <param name="options">
 314        /// Optional client options that define the transport pipeline
 315        /// policies for authentication, retries, etc., that are applied to
 316        /// every request.
 317        /// </param>
 392318        internal BlobBaseClient(Uri blobUri, HttpPipelinePolicy authentication, BlobClientOptions options)
 319        {
 392320            options ??= new BlobClientOptions();
 392321            _uri = blobUri;
 392322            _pipeline = options.Build(authentication);
 392323            _version = options.Version;
 392324            _clientDiagnostics = new ClientDiagnostics(options);
 392325            _customerProvidedKey = options.CustomerProvidedKey;
 392326            _clientSideEncryption = options._clientSideEncryptionOptions?.Clone();
 392327            _encryptionScope = options.EncryptionScope;
 392328            BlobErrors.VerifyHttpsCustomerProvidedKey(_uri, _customerProvidedKey);
 372329            BlobErrors.VerifyCpkAndEncryptionScopeNotBothSet(_customerProvidedKey, _encryptionScope);
 372330        }
 331
 332        /// <summary>
 333        /// Initializes a new instance of the <see cref="BlobBaseClient"/>
 334        /// class.
 335        /// </summary>
 336        /// <param name="blobUri">
 337        /// A <see cref="Uri"/> referencing the blob that includes the
 338        /// name of the account, the name of the container, and the name of
 339        /// the blob.
 340        /// This is likely to be similar to "https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}".
 341        /// </param>
 342        /// <param name="pipeline">
 343        /// The transport pipeline used to send every request.
 344        /// </param>
 345        /// <param name="version">
 346        /// The version of the service to use when sending requests.
 347        /// </param>
 348        /// <param name="clientDiagnostics">Client diagnostics.</param>
 349        /// <param name="customerProvidedKey">Customer provided key.</param>
 350        /// <param name="clientSideEncryption">Client-side encryption options.</param>
 351        /// <param name="encryptionScope">Encryption scope.</param>
 14130352        internal BlobBaseClient(
 14130353            Uri blobUri,
 14130354            HttpPipeline pipeline,
 14130355            BlobClientOptions.ServiceVersion version,
 14130356            ClientDiagnostics clientDiagnostics,
 14130357            CustomerProvidedKey? customerProvidedKey,
 14130358            ClientSideEncryptionOptions clientSideEncryption,
 14130359            string encryptionScope)
 360        {
 14130361            _uri = blobUri;
 14130362            _pipeline = pipeline;
 14130363            _version = version;
 14130364            _clientDiagnostics = clientDiagnostics;
 14130365            _customerProvidedKey = customerProvidedKey;
 14130366            _clientSideEncryption = clientSideEncryption?.Clone();
 14130367            _encryptionScope = encryptionScope;
 14130368            BlobErrors.VerifyHttpsCustomerProvidedKey(_uri, _customerProvidedKey);
 14130369            BlobErrors.VerifyCpkAndEncryptionScopeNotBothSet(_customerProvidedKey, _encryptionScope);
 14130370        }
 371        #endregion ctors
 372
 373        /// <summary>
 374        /// Initializes a new instance of the <see cref="BlobBaseClient"/>
 375        /// class with an identical <see cref="Uri"/> source but the specified
 376        /// <paramref name="snapshot"/> timestamp.
 377        ///
 378        /// For more information, see
 379        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/creating-a-snapshot-of-a-blob">
 380        /// Create a snapshot of a blob</see>.
 381        /// </summary>
 382        /// <param name="snapshot">The snapshot identifier.</param>
 383        /// <returns>A new <see cref="BlobBaseClient"/> instance.</returns>
 384        /// <remarks>
 385        /// Pass null or empty string to remove the snapshot returning a URL
 386        /// to the base blob.
 387        /// </remarks>
 16388        public virtual BlobBaseClient WithSnapshot(string snapshot) => WithSnapshotCore(snapshot);
 389
 390        /// <summary>
 391        /// Creates a new instance of the <see cref="BlobBaseClient"/> class
 392        /// with an identical <see cref="Uri"/> source but the specified
 393        /// <paramref name="snapshot"/> timestamp.
 394        /// </summary>
 395        /// <param name="snapshot">The snapshot identifier.</param>
 396        /// <returns>A new <see cref="BlobBaseClient"/> instance.</returns>
 397        protected virtual BlobBaseClient WithSnapshotCore(string snapshot)
 398        {
 4399            var blobUriBuilder = new BlobUriBuilder(Uri)
 4400            {
 4401                Snapshot = snapshot
 4402            };
 403
 4404            return new BlobBaseClient(
 4405                blobUriBuilder.ToUri(),
 4406                Pipeline,
 4407                Version,
 4408                ClientDiagnostics,
 4409                CustomerProvidedKey,
 4410                ClientSideEncryption,
 4411                EncryptionScope);
 412        }
 413
 414        /// <summary>
 415        /// Initializes a new instance of the <see cref="BlobBaseClient"/>
 416        /// class with an identical <see cref="Uri"/> source but the specified
 417        /// <paramref name="versionId"/> timestamp.
 418        ///
 419        /// </summary>
 420        /// <param name="versionId">The version identifier.</param>
 421        /// <returns>A new <see cref="BlobBaseClient"/> instance.</returns>
 422        /// <remarks>
 423        /// Pass null or empty string to remove the version returning a URL
 424        /// to the base blob.
 425        /// </remarks>
 16426        public virtual BlobBaseClient WithVersion(string versionId) => WithVersionCore(versionId);
 427
 428        /// <summary>
 429        /// Creates a new instance of the <see cref="BlobBaseClient"/> class
 430        /// with an identical <see cref="Uri"/> source but the specified
 431        /// <paramref name="versionId"/> timestamp.
 432        /// </summary>
 433        /// <param name="versionId">The version identifier.</param>
 434        /// <returns>A new <see cref="BlobBaseClient"/> instance.</returns>
 435        private protected virtual BlobBaseClient WithVersionCore(string versionId)
 436        {
 16437            BlobUriBuilder blobUriBuilder = new BlobUriBuilder(Uri)
 16438            {
 16439                VersionId = versionId
 16440            };
 441
 16442            return new BlobBaseClient(
 16443                blobUriBuilder.ToUri(),
 16444                Pipeline,
 16445                Version,
 16446                ClientDiagnostics,
 16447                CustomerProvidedKey,
 16448                ClientSideEncryption,
 16449                EncryptionScope);
 450        }
 451
 452        /// <summary>
 453        /// Sets the various name fields if they are currently null.
 454        /// </summary>
 455        private void SetNameFieldsIfNull()
 456        {
 360457            if (_name == null || _containerName == null || _accountName == null)
 458            {
 260459                var builder = new BlobUriBuilder(Uri);
 260460                _name = builder.BlobName;
 260461                _containerName = builder.BlobContainerName;
 260462                _accountName = builder.AccountName;
 463            }
 360464        }
 465
 466        ///// <summary>
 467        ///// Creates a clone of this instance that references a version ID rather than the base blob.
 468        ///// </summary>
 469        ///// /// <remarks>
 470        ///// Pass null or empty string to remove the version ID returning a URL to the base blob.
 471        ///// </remarks>
 472        ///// <param name="versionId">The version ID to use on this blob. An empty string or null indicates to use the b
 473        ///// <returns>The new <see cref="BlobBaseClient"/> instance referencing the versionId.</returns>
 474        //public virtual BlobBaseClient WithVersionId(string versionId) => this.WithVersionIdImpl(versionId);
 475
 476        //protected virtual BlobBaseClient WithVersionIdImpl(string versionId)
 477        //{
 478        //    var builder = new BlobUriBuilder(this.Uri)
 479        //    {
 480        //        VersionId = versionId
 481        //    };
 482        //    return new BlobUri(builder.ToUri(), this.Pipeline);
 483        //}
 484
 485        #region Download
 486        /// <summary>
 487        /// The <see cref="Download()"/> operation downloads a blob from
 488        /// the service, including its metadata and properties.
 489        ///
 490        /// For more information, see
 491        /// <see href="https://docs.microsoft.com/rest/api/storageservices/get-blob">
 492        /// Get Blob</see>.
 493        /// </summary>
 494        /// <returns>
 495        /// A <see cref="Response{BlobDownloadInfo}"/> describing the
 496        /// downloaded blob.  <see cref="BlobDownloadInfo.Content"/> contains
 497        /// the blob's data.
 498        /// </returns>
 499        /// <remarks>
 500        /// A <see cref="RequestFailedException"/> will be thrown if
 501        /// a failure occurs.
 502        /// </remarks>
 503        public virtual Response<BlobDownloadInfo> Download() =>
 134504            Download(CancellationToken.None);
 505
 506        /// <summary>
 507        /// The <see cref="DownloadAsync()"/> operation downloads a blob from
 508        /// the service, including its metadata and properties.
 509        ///
 510        /// For more information, see
 511        /// <see href="https://docs.microsoft.com/rest/api/storageservices/get-blob">
 512        /// Get Blob</see>.
 513        /// </summary>
 514        /// <returns>
 515        /// A <see cref="Response{BlobDownloadInfo}"/> describing the
 516        /// downloaded blob.  <see cref="BlobDownloadInfo.Content"/> contains
 517        /// the blob's data.
 518        /// </returns>
 519        /// <remarks>
 520        /// A <see cref="RequestFailedException"/> will be thrown if
 521        /// a failure occurs.
 522        /// </remarks>
 523        public virtual async Task<Response<BlobDownloadInfo>> DownloadAsync() =>
 132524            await DownloadAsync(CancellationToken.None).ConfigureAwait(false);
 525
 526        /// <summary>
 527        /// The <see cref="Download(CancellationToken)"/> operation downloads
 528        /// a blob from the service, including its metadata and properties.
 529        ///
 530        /// For more information, see
 531        /// <see href="https://docs.microsoft.com/rest/api/storageservices/get-blob">
 532        /// Get Blob</see>.
 533        /// </summary>
 534        /// <param name="cancellationToken">
 535        /// Optional <see cref="CancellationToken"/> to propagate
 536        /// notifications that the operation should be cancelled.
 537        /// </param>
 538        /// <returns>
 539        /// A <see cref="Response{BlobDownloadInfo}"/> describing the
 540        /// downloaded blob.  <see cref="BlobDownloadInfo.Content"/> contains
 541        /// the blob's data.
 542        /// </returns>
 543        /// <remarks>
 544        /// A <see cref="RequestFailedException"/> will be thrown if
 545        /// a failure occurs.
 546        /// </remarks>
 547        public virtual Response<BlobDownloadInfo> Download(
 548            CancellationToken cancellationToken = default) =>
 174549            Download(
 174550                conditions: default, // Pass anything else so we don't recurse on this overload
 174551                cancellationToken: cancellationToken);
 552
 553        /// <summary>
 554        /// The <see cref="DownloadAsync(CancellationToken)"/> operation
 555        /// downloads a blob from the service, including its metadata and
 556        /// properties.
 557        ///
 558        /// For more information, see
 559        /// <see href="https://docs.microsoft.com/rest/api/storageservices/get-blob">
 560        /// Get Blob</see>.
 561        /// </summary>
 562        /// <param name="cancellationToken">
 563        /// Optional <see cref="CancellationToken"/> to propagate
 564        /// notifications that the operation should be cancelled.
 565        /// </param>
 566        /// <returns>
 567        /// A <see cref="Response{BlobDownloadInfo}"/> describing the
 568        /// downloaded blob.  <see cref="BlobDownloadInfo.Content"/> contains
 569        /// the blob's data.
 570        /// </returns>
 571        /// <remarks>
 572        /// A <see cref="RequestFailedException"/> will be thrown if
 573        /// a failure occurs.
 574        /// </remarks>
 575        public virtual async Task<Response<BlobDownloadInfo>> DownloadAsync(
 576            CancellationToken cancellationToken) =>
 178577            await DownloadAsync(
 178578                conditions: default, // Pass anything else so we don't recurse on this overload
 178579                cancellationToken: cancellationToken)
 178580                .ConfigureAwait(false);
 581
 582        /// <summary>
 583        /// The <see cref="Download(HttpRange, BlobRequestConditions, bool, CancellationToken)"/>
 584        /// operation downloads a blob from the service, including its metadata
 585        /// and properties.
 586        ///
 587        /// For more information, see
 588        /// <see href="https://docs.microsoft.com/rest/api/storageservices/get-blob">
 589        /// Get Blob</see>.
 590        /// </summary>
 591        /// <param name="range">
 592        /// If provided, only download the bytes of the blob in the specified
 593        /// range.  If not provided, download the entire blob.
 594        /// </param>
 595        /// <param name="conditions">
 596        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 597        /// downloading this blob.
 598        /// </param>
 599        /// <param name="rangeGetContentHash">
 600        /// When set to true and specified together with the <paramref name="range"/>,
 601        /// the service returns the MD5 hash for the range, as long as the
 602        /// range is less than or equal to 4 MB in size.  If this value is
 603        /// specified without <paramref name="range"/> or set to true when the
 604        /// range exceeds 4 MB in size, a <see cref="RequestFailedException"/>
 605        /// is thrown.
 606        /// </param>
 607        /// <param name="cancellationToken">
 608        /// Optional <see cref="CancellationToken"/> to propagate
 609        /// notifications that the operation should be cancelled.
 610        /// </param>
 611        /// <returns>
 612        /// A <see cref="Response{BlobDownloadInfo}"/> describing the
 613        /// downloaded blob.  <see cref="BlobDownloadInfo.Content"/> contains
 614        /// the blob's data.
 615        /// </returns>
 616        /// <remarks>
 617        /// A <see cref="RequestFailedException"/> will be thrown if
 618        /// a failure occurs.
 619        /// </remarks>
 620        public virtual Response<BlobDownloadInfo> Download(
 621            HttpRange range = default,
 622            BlobRequestConditions conditions = default,
 623            bool rangeGetContentHash = default,
 624            CancellationToken cancellationToken = default) =>
 420625            DownloadInternal(
 420626                range,
 420627                conditions,
 420628                rangeGetContentHash,
 420629                false, // async
 420630                cancellationToken)
 420631                .EnsureCompleted();
 632
 633        /// <summary>
 634        /// The <see cref="DownloadAsync(HttpRange, BlobRequestConditions, bool, CancellationToken)"/>
 635        /// operation downloads a blob from the service, including its metadata
 636        /// and properties.
 637        ///
 638        /// For more information, see
 639        /// <see href="https://docs.microsoft.com/rest/api/storageservices/get-blob">
 640        /// Get Blob</see>.
 641        /// </summary>
 642        /// <param name="range">
 643        /// If provided, only download the bytes of the blob in the specified
 644        /// range.  If not provided, download the entire blob.
 645        /// </param>
 646        /// <param name="conditions">
 647        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 648        /// downloading this blob.
 649        /// </param>
 650        /// <param name="rangeGetContentHash">
 651        /// When set to true and specified together with the <paramref name="range"/>,
 652        /// the service returns the MD5 hash for the range, as long as the
 653        /// range is less than or equal to 4 MB in size.  If this value is
 654        /// specified without <paramref name="range"/> or set to true when the
 655        /// range exceeds 4 MB in size, a <see cref="RequestFailedException"/>
 656        /// is thrown.
 657        /// </param>
 658        /// <param name="cancellationToken">
 659        /// Optional <see cref="CancellationToken"/> to propagate
 660        /// notifications that the operation should be cancelled.
 661        /// </param>
 662        /// <returns>
 663        /// A <see cref="Response{BlobDownloadInfo}"/> describing the
 664        /// downloaded blob.  <see cref="BlobDownloadInfo.Content"/> contains
 665        /// the blob's data.
 666        /// </returns>
 667        /// <remarks>
 668        /// A <see cref="RequestFailedException"/> will be thrown if
 669        /// a failure occurs.
 670        /// </remarks>
 671        public virtual async Task<Response<BlobDownloadInfo>> DownloadAsync(
 672            HttpRange range = default,
 673            BlobRequestConditions conditions = default,
 674            bool rangeGetContentHash = default,
 675            CancellationToken cancellationToken = default) =>
 560676            await DownloadInternal(
 560677                range,
 560678                conditions,
 560679                rangeGetContentHash,
 560680                true, // async
 560681                cancellationToken)
 560682                .ConfigureAwait(false);
 683
 684        /// <summary>
 685        /// The <see cref="DownloadInternal"/> operation downloads a blob
 686        /// from the service, including its metadata and properties.
 687        ///
 688        /// For more information, see
 689        /// <see href="https://docs.microsoft.com/rest/api/storageservices/get-blob">
 690        /// Get Blob</see>.
 691        /// </summary>
 692        /// <param name="range">
 693        /// If provided, only download the bytes of the blob in the specified
 694        /// range.  If not provided, download the entire blob.
 695        /// </param>
 696        /// <param name="conditions">
 697        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 698        /// downloading this blob.
 699        /// </param>
 700        /// <param name="rangeGetContentHash">
 701        /// When set to true and specified together with the <paramref name="range"/>,
 702        /// the service returns the MD5 hash for the range, as long as the
 703        /// range is less than or equal to 4 MB in size.  If this value is
 704        /// specified without <paramref name="range"/> or set to true when the
 705        /// range exceeds 4 MB in size, a <see cref="RequestFailedException"/>
 706        /// is thrown.
 707        /// </param>
 708        /// <param name="async">
 709        /// Whether to invoke the operation asynchronously.
 710        /// </param>
 711        /// <param name="cancellationToken">
 712        /// Optional <see cref="CancellationToken"/> to propagate
 713        /// notifications that the operation should be cancelled.
 714        /// </param>
 715        /// <returns>
 716        /// A <see cref="Response{BlobDownloadInfo}"/> describing the
 717        /// downloaded blob.  <see cref="BlobDownloadInfo.Content"/> contains
 718        /// the blob's data.
 719        /// </returns>
 720        /// <remarks>
 721        /// A <see cref="RequestFailedException"/> will be thrown if
 722        /// a failure occurs.
 723        /// </remarks>
 724        private async Task<Response<BlobDownloadInfo>> DownloadInternal(
 725            HttpRange range,
 726            BlobRequestConditions conditions,
 727            bool rangeGetContentHash,
 728            bool async,
 729            CancellationToken cancellationToken)
 730        {
 1556731            HttpRange requestedRange = range;
 1556732            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 733            {
 734                Pipeline.LogMethodEnter(nameof(BlobBaseClient), message: $"{nameof(Uri)}: {Uri}");
 735                try
 736                {
 1556737                    if (UsingClientSideEncryption)
 738                    {
 0739                        range = BlobClientSideDecryptor.GetEncryptedBlobRange(range);
 740                    }
 741
 742                    // Start downloading the blob
 1556743                    (Response<FlattenedDownloadProperties> response, Stream stream) = await StartDownloadAsync(
 1556744                        range,
 1556745                        conditions,
 1556746                        rangeGetContentHash,
 1556747                        async: async,
 1556748                        cancellationToken: cancellationToken)
 1556749                        .ConfigureAwait(false);
 750
 751                    // Return an exploding Response on 304
 1452752                    if (response.IsUnavailable())
 753                    {
 20754                        return response.GetRawResponse().AsNoBodyResponse<BlobDownloadInfo>();
 755                    }
 756
 757                    // Wrap the response Content in a RetriableStream so we
 758                    // can return it before it's finished downloading, but still
 759                    // allow retrying if it fails.
 1432760                    stream = RetriableStream.Create(
 1432761                        stream,
 1432762                         startOffset =>
 0763                            StartDownloadAsync(
 0764                                    range,
 0765                                    conditions,
 0766                                    rangeGetContentHash,
 0767                                    startOffset,
 0768                                    async,
 0769                                    cancellationToken)
 0770                                .EnsureCompleted()
 0771                            .Item2,
 1432772                        async startOffset =>
 0773                            (await StartDownloadAsync(
 0774                                range,
 0775                                conditions,
 0776                                rangeGetContentHash,
 0777                                startOffset,
 0778                                async,
 0779                                cancellationToken)
 0780                                .ConfigureAwait(false))
 0781                            .Item2,
 1432782                        Pipeline.ResponseClassifier,
 1432783                        Constants.MaxReliabilityRetries);
 784
 785                    // if using clientside encryption, wrap the auto-retry stream in a decryptor
 786                    // we already return a nonseekable stream; returning a crypto stream is fine
 1432787                    if (UsingClientSideEncryption)
 788                    {
 0789                        stream = await new BlobClientSideDecryptor(new ClientSideDecryptor(ClientSideEncryption))
 0790                            .DecryptInternal(stream, response.Value.Metadata, requestedRange, response.Value.ContentRang
 791                    }
 792
 1432793                    response.Value.Content = stream;
 794
 795                    // Wrap the FlattenedDownloadProperties into a BlobDownloadOperation
 796                    // to make the Content easier to find
 1432797                    return Response.FromValue(new BlobDownloadInfo(response.Value), response.GetRawResponse());
 798                }
 104799                catch (Exception ex)
 800                {
 801                    Pipeline.LogException(ex);
 104802                    throw;
 803                }
 804                finally
 805                {
 806                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 807                }
 808            }
 1452809        }
 810
 811        /// <summary>
 812        /// The <see cref="StartDownloadAsync"/> operation starts downloading
 813        /// a blob from the service from a given <paramref name="startOffset"/>.
 814        /// </summary>
 815        /// <param name="range">
 816        /// If provided, only download the bytes of the blob in the specified
 817        /// range.  If not provided, download the entire blob.
 818        /// </param>
 819        /// <param name="conditions">
 820        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 821        /// downloading this blob.
 822        /// </param>
 823        /// <param name="rangeGetContentHash">
 824        /// When set to true and specified together with the <paramref name="range"/>,
 825        /// the service returns the MD5 hash for the range, as long as the
 826        /// range is less than or equal to 4 MB in size.  If this value is
 827        /// specified without <paramref name="range"/> or set to true when the
 828        /// range exceeds 4 MB in size, a <see cref="RequestFailedException"/>
 829        /// is thrown.
 830        /// </param>
 831        /// <param name="startOffset">
 832        /// Starting offset to request - in the event of a retry.
 833        /// </param>
 834        /// <param name="async">
 835        /// Whether to invoke the operation asynchronously.
 836        /// </param>
 837        /// <param name="cancellationToken">
 838        /// Optional <see cref="CancellationToken"/> to propagate
 839        /// notifications that the operation should be cancelled.
 840        /// </param>
 841        /// <returns>
 842        /// A <see cref="Response{BlobDownloadInfo}"/> describing the
 843        /// downloaded blob.  <see cref="BlobDownloadInfo.Content"/> contains
 844        /// the blob's data.
 845        /// </returns>
 846        /// <remarks>
 847        /// A <see cref="RequestFailedException"/> will be thrown if
 848        /// a failure occurs.
 849        /// </remarks>
 850        private async Task<(Response<FlattenedDownloadProperties>, Stream)> StartDownloadAsync(
 851            HttpRange range = default,
 852            BlobRequestConditions conditions = default,
 853            bool rangeGetContentHash = default,
 854            long startOffset = 0,
 855            bool async = true,
 856            CancellationToken cancellationToken = default)
 857        {
 1556858            HttpRange? pageRange = null;
 1556859            if (range != default || startOffset != 0)
 860            {
 1104861                pageRange = new HttpRange(
 1104862                    range.Offset + startOffset,
 1104863                    range.Length.HasValue ?
 1104864                        range.Length.Value - startOffset :
 1104865                        (long?)null);
 866            }
 867
 868            Pipeline.LogTrace($"Download {Uri} with range: {pageRange}");
 869
 1556870            (Response<FlattenedDownloadProperties> response, Stream stream) =
 1556871                await BlobRestClient.Blob.DownloadAsync(
 1556872                    ClientDiagnostics,
 1556873                    Pipeline,
 1556874                    Uri,
 1556875                    version: Version.ToVersionString(),
 1556876                    range: pageRange?.ToString(),
 1556877                    leaseId: conditions?.LeaseId,
 1556878                    rangeGetContentHash: rangeGetContentHash ? (bool?)true : null,
 1556879                    encryptionKey: CustomerProvidedKey?.EncryptionKey,
 1556880                    encryptionKeySha256: CustomerProvidedKey?.EncryptionKeyHash,
 1556881                    encryptionAlgorithm: CustomerProvidedKey?.EncryptionAlgorithm,
 1556882                    ifModifiedSince: conditions?.IfModifiedSince,
 1556883                    ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 1556884                    ifMatch: conditions?.IfMatch,
 1556885                    ifNoneMatch: conditions?.IfNoneMatch,
 1556886                    ifTags: conditions?.TagConditions,
 1556887                    async: async,
 1556888                    operationName: "BlobBaseClient.Download",
 1556889                    cancellationToken: cancellationToken)
 1556890                    .ConfigureAwait(false);
 891
 892            // Watch out for exploding Responses
 1452893            long length = response.IsUnavailable() ? 0 : response.Value.ContentLength;
 894            Pipeline.LogTrace($"Response: {response.GetRawResponse().Status}, ContentLength: {length}");
 895
 1452896            return (response, stream);
 1452897        }
 898        #endregion Download
 899
 900        #region Parallel Download
 901        /// <summary>
 902        /// The <see cref="DownloadTo(Stream)"/> operation downloads a blob using parallel requests,
 903        /// and writes the content to <paramref name="destination"/>.
 904        /// </summary>
 905        /// <param name="destination">
 906        /// A <see cref="Stream"/> to write the downloaded content to.
 907        /// </param>
 908        /// <returns>
 909        /// A <see cref="Response"/> describing the operation.
 910        /// </returns>
 911        /// <remarks>
 912        /// A <see cref="RequestFailedException"/> will be thrown if
 913        /// a failure occurs.
 914        /// </remarks>
 915        public virtual Response DownloadTo(Stream destination) =>
 4916            DownloadTo(destination, CancellationToken.None);
 917
 918        /// <summary>
 919        /// The <see cref="DownloadTo(string)"/> operation downloads a blob using parallel requests,
 920        /// and writes the content to <paramref name="path"/>.
 921        /// </summary>
 922        /// <param name="path">
 923        /// A file path to write the downloaded content to.
 924        /// </param>
 925        /// <returns>
 926        /// A <see cref="Response"/> describing the operation.
 927        /// </returns>
 928        /// <remarks>
 929        /// A <see cref="RequestFailedException"/> will be thrown if
 930        /// a failure occurs.
 931        /// </remarks>
 932        public virtual Response DownloadTo(string path) =>
 2933            DownloadTo(path, CancellationToken.None);
 934
 935        /// <summary>
 936        /// The <see cref="DownloadToAsync(Stream)"/> downloads a blob using parallel requests,
 937        /// and writes the content to <paramref name="destination"/>.
 938        /// </summary>
 939        /// <param name="destination">
 940        /// A <see cref="Stream"/> to write the downloaded content to.
 941        /// </param>
 942        /// <returns>
 943        /// A <see cref="Response"/> describing the operation.
 944        /// </returns>
 945        /// <remarks>
 946        /// A <see cref="RequestFailedException"/> will be thrown if
 947        /// a failure occurs.
 948        /// </remarks>
 949        public virtual async Task<Response> DownloadToAsync(Stream destination) =>
 4950            await DownloadToAsync(destination, CancellationToken.None).ConfigureAwait(false);
 951
 952        /// <summary>
 953        /// The <see cref="DownloadToAsync(string)"/> downloads a blob using parallel requests,
 954        /// and writes the content to <paramref name="path"/>.
 955        /// </summary>
 956        /// <param name="path">
 957        /// A file path to write the downloaded content to.
 958        /// </param>
 959        /// <returns>
 960        /// A <see cref="Response"/> describing the operation.
 961        /// </returns>
 962        /// <remarks>
 963        /// A <see cref="RequestFailedException"/> will be thrown if
 964        /// a failure occurs.
 965        /// </remarks>
 966        public virtual async Task<Response> DownloadToAsync(string path) =>
 2967            await DownloadToAsync(path, CancellationToken.None).ConfigureAwait(false);
 968
 969        /// <summary>
 970        /// The <see cref="DownloadTo(Stream, CancellationToken)"/> operation
 971        /// downloads a blob using parallel requests,
 972        /// and writes the content to <paramref name="destination"/>.
 973        /// </summary>
 974        /// <param name="destination">
 975        /// A <see cref="Stream"/> to write the downloaded content to.
 976        /// </param>
 977        /// <param name="cancellationToken">
 978        /// Optional <see cref="CancellationToken"/> to propagate
 979        /// notifications that the operation should be cancelled.
 980        /// </param>
 981        /// <returns>
 982        /// A <see cref="Response"/> describing the operation.
 983        /// </returns>
 984        /// <remarks>
 985        /// A <see cref="RequestFailedException"/> will be thrown if
 986        /// a failure occurs.
 987        /// </remarks>
 988        public virtual Response DownloadTo(
 989            Stream destination,
 990            CancellationToken cancellationToken) =>
 6991            DownloadTo(
 6992                destination,
 6993                conditions: default, // Pass anything else so we don't recurse on this overload
 6994                cancellationToken: cancellationToken);
 995
 996        /// <summary>
 997        /// The <see cref="DownloadTo(string, CancellationToken)"/> operation
 998        /// downloads a blob using parallel requests,
 999        /// and writes the content to <paramref name="path"/>.
 1000        /// </summary>
 1001        /// <param name="path">
 1002        /// A file path to write the downloaded content to.
 1003        /// </param>
 1004        /// <param name="cancellationToken">
 1005        /// Optional <see cref="CancellationToken"/> to propagate
 1006        /// notifications that the operation should be cancelled.
 1007        /// </param>
 1008        /// <returns>
 1009        /// A <see cref="Response"/> describing the operation.
 1010        /// </returns>
 1011        /// <remarks>
 1012        /// A <see cref="RequestFailedException"/> will be thrown if
 1013        /// a failure occurs.
 1014        /// </remarks>
 1015        public virtual Response DownloadTo(
 1016            string path,
 1017            CancellationToken cancellationToken) =>
 41018            DownloadTo(
 41019                path,
 41020                conditions: default, // Pass anything else so we don't recurse on this overload
 41021                cancellationToken: cancellationToken);
 1022
 1023        /// <summary>
 1024        /// The <see cref="DownloadToAsync(Stream, CancellationToken)"/> operation
 1025        /// downloads a blob using parallel requests,
 1026        /// and writes the content to <paramref name="destination"/>.
 1027        /// </summary>
 1028        /// <param name="destination">
 1029        /// A <see cref="Stream"/> to write the downloaded content to.
 1030        /// </param>
 1031        /// <param name="cancellationToken">
 1032        /// Optional <see cref="CancellationToken"/> to propagate
 1033        /// notifications that the operation should be cancelled.
 1034        /// </param>
 1035        /// <returns>
 1036        /// A <see cref="Response"/> describing the operation.
 1037        /// </returns>
 1038        /// <remarks>
 1039        /// A <see cref="RequestFailedException"/> will be thrown if
 1040        /// a failure occurs.
 1041        /// </remarks>
 1042        public virtual async Task<Response> DownloadToAsync(
 1043            Stream destination,
 1044            CancellationToken cancellationToken) =>
 61045            await DownloadToAsync(
 61046                destination,
 61047                conditions: default, // Pass anything else so we don't recurse on this overload
 61048                cancellationToken: cancellationToken)
 61049                .ConfigureAwait(false);
 1050
 1051        /// <summary>
 1052        /// The <see cref="DownloadToAsync(string, CancellationToken)"/> operation
 1053        /// downloads a blob using parallel requests,
 1054        /// and writes the content to <paramref name="path"/>.
 1055        /// </summary>
 1056        /// <param name="path">
 1057        /// A file path to write the downloaded content to.
 1058        /// </param>
 1059        /// <param name="cancellationToken">
 1060        /// Optional <see cref="CancellationToken"/> to propagate
 1061        /// notifications that the operation should be cancelled.
 1062        /// </param>
 1063        /// <returns>
 1064        /// A <see cref="Response"/> describing the operation.
 1065        /// </returns>
 1066        /// <remarks>
 1067        /// A <see cref="RequestFailedException"/> will be thrown if
 1068        /// a failure occurs.
 1069        /// </remarks>
 1070        public virtual async Task<Response> DownloadToAsync(
 1071            string path,
 1072            CancellationToken cancellationToken) =>
 41073            await DownloadToAsync(
 41074                path,
 41075                conditions: default, // Pass anything else so we don't recurse on this overload
 41076                cancellationToken: cancellationToken)
 41077                .ConfigureAwait(false);
 1078
 1079        /// <summary>
 1080        /// The <see cref="DownloadTo(Stream, BlobRequestConditions, StorageTransferOptions, CancellationToken)"/>
 1081        /// operation downloads a blob using parallel requests,
 1082        /// and writes the content to <paramref name="destination"/>.
 1083        /// </summary>
 1084        /// <param name="destination">
 1085        /// A <see cref="Stream"/> to write the downloaded content to.
 1086        /// </param>
 1087        /// <param name="conditions">
 1088        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 1089        /// the creation of this new block blob.
 1090        /// </param>
 1091        /// <param name="transferOptions">
 1092        /// Optional <see cref="StorageTransferOptions"/> to configure
 1093        /// parallel transfer behavior.
 1094        /// </param>
 1095        /// <param name="cancellationToken">
 1096        /// Optional <see cref="CancellationToken"/> to propagate
 1097        /// notifications that the operation should be cancelled.
 1098        /// </param>
 1099        /// <returns>
 1100        /// A <see cref="Response"/> describing the operation.
 1101        /// </returns>
 1102        /// <remarks>
 1103        /// A <see cref="RequestFailedException"/> will be thrown if
 1104        /// a failure occurs.
 1105        /// </remarks>
 1106        public virtual Response DownloadTo(
 1107            Stream destination,
 1108            BlobRequestConditions conditions = default,
 1109            ///// <param name="progressHandler">
 1110            ///// Optional <see cref="IProgress{Long}"/> to provide
 1111            ///// progress updates about data transfers.
 1112            ///// </param>
 1113            //IProgress<long> progressHandler = default,
 1114            StorageTransferOptions transferOptions = default,
 1115            CancellationToken cancellationToken = default) =>
 181116            StagedDownloadAsync(
 181117                destination,
 181118                conditions,
 181119                //progressHandler, // TODO: #8506
 181120                transferOptions: transferOptions,
 181121                async: false,
 181122                cancellationToken: cancellationToken)
 181123                .EnsureCompleted();
 1124
 1125        /// <summary>
 1126        /// The <see cref="DownloadTo(string, BlobRequestConditions, StorageTransferOptions, CancellationToken)"/>
 1127        /// operation downloads a blob using parallel requests,
 1128        /// and writes the content to <paramref name="path"/>.
 1129        /// </summary>
 1130        /// <param name="path">
 1131        /// A file path to write the downloaded content to.
 1132        /// </param>
 1133        /// <param name="conditions">
 1134        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 1135        /// the creation of this new block blob.
 1136        /// </param>
 1137        /// <param name="transferOptions">
 1138        /// Optional <see cref="StorageTransferOptions"/> to configure
 1139        /// parallel transfer behavior.
 1140        /// </param>
 1141        /// <param name="cancellationToken">
 1142        /// Optional <see cref="CancellationToken"/> to propagate
 1143        /// notifications that the operation should be cancelled.
 1144        /// </param>
 1145        /// <returns>
 1146        /// A <see cref="Response"/> describing the operation.
 1147        /// </returns>
 1148        /// <remarks>
 1149        /// A <see cref="RequestFailedException"/> will be thrown if
 1150        /// a failure occurs.
 1151        /// </remarks>
 1152        public virtual Response DownloadTo(
 1153            string path,
 1154            BlobRequestConditions conditions = default,
 1155            ///// <param name="progressHandler">
 1156            ///// Optional <see cref="IProgress{Long}"/> to provide
 1157            ///// progress updates about data transfers.
 1158            ///// </param>
 1159            //IProgress<long> progressHandler = default,
 1160            StorageTransferOptions transferOptions = default,
 1161            CancellationToken cancellationToken = default)
 1162        {
 61163            using Stream destination = File.Create(path);
 61164            return StagedDownloadAsync(
 61165                destination,
 61166                conditions,
 61167                //progressHandler, // TODO: #8506
 61168                transferOptions: transferOptions,
 61169                async: false,
 61170                cancellationToken: cancellationToken)
 61171                .EnsureCompleted();
 61172        }
 1173
 1174        /// <summary>
 1175        /// The <see cref="DownloadToAsync(Stream, BlobRequestConditions, StorageTransferOptions, CancellationToken)"/>
 1176        /// operation downloads a blob using parallel requests,
 1177        /// and writes the content to <paramref name="destination"/>.
 1178        /// </summary>
 1179        /// <param name="destination">
 1180        /// A <see cref="Stream"/> to write the downloaded content to.
 1181        /// </param>
 1182        /// <param name="conditions">
 1183        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 1184        /// the creation of this new block blob.
 1185        /// </param>
 1186        /// <param name="transferOptions">
 1187        /// Optional <see cref="StorageTransferOptions"/> to configure
 1188        /// parallel transfer behavior.
 1189        /// </param>
 1190        /// <param name="cancellationToken">
 1191        /// Optional <see cref="CancellationToken"/> to propagate
 1192        /// notifications that the operation should be cancelled.
 1193        /// </param>
 1194        /// <returns>
 1195        /// A <see cref="Response"/> describing the operation.
 1196        /// </returns>
 1197        /// <remarks>
 1198        /// A <see cref="RequestFailedException"/> will be thrown if
 1199        /// a failure occurs.
 1200        /// </remarks>
 1201        public virtual async Task<Response> DownloadToAsync(
 1202            Stream destination,
 1203            BlobRequestConditions conditions = default,
 1204            ///// <param name="progressHandler">
 1205            ///// Optional <see cref="IProgress{Long}"/> to provide
 1206            ///// progress updates about data transfers.
 1207            ///// </param>
 1208            //IProgress<long> progressHandler = default,
 1209            StorageTransferOptions transferOptions = default,
 1210            CancellationToken cancellationToken = default) =>
 381211            await StagedDownloadAsync(
 381212                destination,
 381213                conditions,
 381214                //progressHandler, // TODO: #8506
 381215                transferOptions: transferOptions,
 381216                async: true,
 381217                cancellationToken: cancellationToken)
 381218                .ConfigureAwait(false);
 1219
 1220        /// <summary>
 1221        /// The <see cref="DownloadToAsync(string, BlobRequestConditions, StorageTransferOptions, CancellationToken)"/>
 1222        /// operation downloads a blob using parallel requests,
 1223        /// and writes the content to <paramref name="path"/>.
 1224        /// </summary>
 1225        /// <param name="path">
 1226        /// A file path to write the downloaded content to.
 1227        /// </param>
 1228        /// <param name="conditions">
 1229        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 1230        /// the creation of this new block blob.
 1231        /// </param>
 1232        /// <param name="transferOptions">
 1233        /// Optional <see cref="StorageTransferOptions"/> to configure
 1234        /// parallel transfer behavior.
 1235        /// </param>
 1236        /// <param name="cancellationToken">
 1237        /// Optional <see cref="CancellationToken"/> to propagate
 1238        /// notifications that the operation should be cancelled.
 1239        /// </param>
 1240        /// <returns>
 1241        /// A <see cref="Response"/> describing the operation.
 1242        /// </returns>
 1243        /// <remarks>
 1244        /// A <see cref="RequestFailedException"/> will be thrown if
 1245        /// a failure occurs.
 1246        /// </remarks>
 1247        public virtual async Task<Response> DownloadToAsync(
 1248            string path,
 1249            BlobRequestConditions conditions = default,
 1250            ///// <param name="progressHandler">
 1251            ///// Optional <see cref="IProgress{Long}"/> to provide
 1252            ///// progress updates about data transfers.
 1253            ///// </param>
 1254            //IProgress<long> progressHandler = default,
 1255            StorageTransferOptions transferOptions = default,
 1256            CancellationToken cancellationToken = default)
 1257        {
 181258            using Stream destination = File.Create(path);
 181259            return await StagedDownloadAsync(
 181260                destination,
 181261                conditions,
 181262                //progressHandler, // TODO: #8506
 181263                transferOptions: transferOptions,
 181264                async: true,
 181265                cancellationToken: cancellationToken)
 181266                .ConfigureAwait(false);
 181267        }
 1268
 1269        /// <summary>
 1270        /// This operation will download a blob of arbitrary size by downloading it as individually staged
 1271        /// partitions if it's larger than the
 1272        /// <paramref name="transferOptions"/> MaximumTransferLength.
 1273        /// </summary>
 1274        /// <param name="destination">
 1275        /// A <see cref="Stream"/> to write the downloaded content to.
 1276        /// </param>
 1277        /// <param name="conditions">
 1278        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 1279        /// the creation of this new block blob.
 1280        /// </param>
 1281        /// <param name="transferOptions">
 1282        /// Optional <see cref="StorageTransferOptions"/> to configure
 1283        /// parallel transfer behavior.
 1284        /// </param>
 1285        /// <param name="async">
 1286        /// Whether to invoke the operation asynchronously.
 1287        /// </param>
 1288        /// <param name="cancellationToken">
 1289        /// Optional <see cref="CancellationToken"/> to propagate
 1290        /// notifications that the operation should be cancelled.
 1291        /// </param>
 1292        /// <returns>
 1293        /// A <see cref="Response"/> describing the operation.
 1294        /// </returns>
 1295        /// <remarks>
 1296        /// A <see cref="RequestFailedException"/> will be thrown if
 1297        /// a failure occurs.
 1298        /// </remarks>
 1299        internal async Task<Response> StagedDownloadAsync(
 1300            Stream destination,
 1301            BlobRequestConditions conditions = default,
 1302            ///// <param name="progressHandler">
 1303            ///// Optional <see cref="IProgress{Long}"/> to provide
 1304            ///// progress updates about data transfers.
 1305            ///// </param>
 1306            //IProgress<long> progressHandler, // TODO: #8506
 1307            StorageTransferOptions transferOptions = default,
 1308            bool async = true,
 1309            CancellationToken cancellationToken = default)
 1310        {
 1201311            var client = new BlobBaseClient(Uri, Pipeline, Version, ClientDiagnostics, CustomerProvidedKey, ClientSideEn
 1312
 1201313            PartitionedDownloader downloader = new PartitionedDownloader(client, transferOptions);
 1314
 1201315            if (async)
 1316            {
 961317                return await downloader.DownloadToAsync(destination, conditions, cancellationToken).ConfigureAwait(false
 1318            }
 1319            else
 1320            {
 241321                return downloader.DownloadTo(destination, conditions, cancellationToken);
 1322            }
 1161323        }
 1324        #endregion Parallel Download
 1325
 1326        #region OpenRead
 1327        /// <summary>
 1328        /// Opens a stream for reading from the blob.  The stream will only download
 1329        /// the blob as the stream is read from.
 1330        /// </summary>
 1331        /// <param name="position">
 1332        /// The position within the blob to begin the stream.
 1333        /// Defaults to the beginning of the blob.
 1334        /// </param>
 1335        /// <param name="bufferSize">
 1336        /// The buffer size to use when the stream downloads parts
 1337        /// of the blob.  Defaults to 1 MB.
 1338        /// </param>
 1339        /// <param name="conditions">
 1340        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 1341        /// the download of the blob.
 1342        /// </param>
 1343        /// <param name="cancellationToken">
 1344        /// Optional <see cref="CancellationToken"/> to propagate
 1345        /// notifications that the operation should be cancelled.
 1346        /// </param>
 1347        /// <returns>
 1348        /// Returns a stream that will download the blob as the stream
 1349        /// is read from.
 1350        /// </returns>
 1351#pragma warning disable AZC0015 // Unexpected client method return type.
 1352        public virtual Stream OpenRead(
 1353#pragma warning restore AZC0015 // Unexpected client method return type.
 1354            long position = 0,
 1355            int? bufferSize = default,
 1356            BlobRequestConditions conditions = default,
 1357            CancellationToken cancellationToken = default)
 701358            => OpenReadInternal(
 701359                position,
 701360                bufferSize,
 701361                conditions,
 701362                async: false,
 701363                cancellationToken).EnsureCompleted();
 1364
 1365        /// <summary>
 1366        /// Opens a stream for reading from the blob.  The stream will only download
 1367        /// the blob as the stream is read from.
 1368        /// </summary>
 1369        /// <param name="allowBlobModifications">
 1370        /// If true, you can continue streaming a blob even if it has been modified.
 1371        /// </param>
 1372        /// <param name="position">
 1373        /// The position within the blob to begin the stream.
 1374        /// Defaults to the beginning of the blob.
 1375        /// </param>
 1376        /// <param name="bufferSize">
 1377        /// The buffer size to use when the stream downloads parts
 1378        /// of the blob.  Defaults to 1 MB.
 1379        /// </param>
 1380        /// <param name="cancellationToken">
 1381        /// Optional <see cref="CancellationToken"/> to propagate
 1382        /// notifications that the operation should be cancelled.
 1383        /// </param>
 1384        /// <returns>
 1385        /// Returns a stream that will download the blob as the stream
 1386        /// is read from.
 1387        /// </returns>
 1388#pragma warning disable AZC0015 // Unexpected client method return type.
 1389        public virtual Stream OpenRead(
 1390#pragma warning restore AZC0015 // Unexpected client method return type.
 1391            bool allowBlobModifications,
 1392            long position = 0,
 1393            int? bufferSize = default,
 1394            CancellationToken cancellationToken = default)
 21395                => OpenRead(
 21396                    position,
 21397                    bufferSize,
 21398                    allowBlobModifications ? new BlobRequestConditions() : null,
 21399                    cancellationToken);
 1400
 1401        /// <summary>
 1402        /// Opens a stream for reading from the blob.  The stream will only download
 1403        /// the blob as the stream is read from.
 1404        /// </summary>
 1405        /// <param name="position">
 1406        /// The position within the blob to begin the stream.
 1407        /// Defaults to the beginning of the blob.
 1408        /// </param>
 1409        /// <param name="bufferSize">
 1410        /// The buffer size to use when the stream downloads parts
 1411        /// of the blob.  Defaults to 1 MB.
 1412        /// </param>
 1413        /// <param name="conditions">
 1414        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 1415        /// the download of the blob.
 1416        /// </param>
 1417        /// <param name="cancellationToken">
 1418        /// Optional <see cref="CancellationToken"/> to propagate
 1419        /// notifications that the operation should be cancelled.
 1420        /// </param>
 1421        /// <returns>
 1422        /// Returns a stream that will download the blob as the stream
 1423        /// is read from.
 1424        /// </returns>
 1425#pragma warning disable AZC0015 // Unexpected client method return type.
 1426        public virtual async Task<Stream> OpenReadAsync(
 1427#pragma warning restore AZC0015 // Unexpected client method return type.
 1428            long position = 0,
 1429            int? bufferSize = default,
 1430            BlobRequestConditions conditions = default,
 1431            CancellationToken cancellationToken = default)
 781432            => await OpenReadInternal(
 781433                position,
 781434                bufferSize,
 781435                conditions,
 781436                async: true,
 781437                cancellationToken).ConfigureAwait(false);
 1438
 1439        /// <summary>
 1440        /// Opens a stream for reading from the blob.  The stream will only download
 1441        /// the blob as the stream is read from.
 1442        /// </summary>
 1443        /// <param name="allowBlobModifications">
 1444        /// If true, you can continue streaming a blob even if it has been modified.
 1445        /// </param>
 1446        /// <param name="position">
 1447        /// The position within the blob to begin the stream.
 1448        /// Defaults to the beginning of the blob.
 1449        /// </param>
 1450        /// <param name="bufferSize">
 1451        /// The buffer size to use when the stream downloads parts
 1452        /// of the blob.  Defaults to 1 MB.
 1453        /// </param>
 1454        /// <param name="cancellationToken">
 1455        /// Optional <see cref="CancellationToken"/> to propagate
 1456        /// notifications that the operation should be cancelled.
 1457        /// </param>
 1458        /// <returns>
 1459        /// Returns a stream that will download the blob as the stream
 1460        /// is read from.
 1461        /// </returns>
 1462#pragma warning disable AZC0015 // Unexpected client method return type.
 1463        public virtual async Task<Stream> OpenReadAsync(
 1464#pragma warning restore AZC0015 // Unexpected client method return type.
 1465            bool allowBlobModifications,
 1466            long position = 0,
 1467            int? bufferSize = default,
 1468            CancellationToken cancellationToken = default)
 21469                => await OpenReadAsync(
 21470                    position,
 21471                    bufferSize,
 21472                    allowBlobModifications ? new BlobRequestConditions() : null,
 21473                    cancellationToken)
 21474                    .ConfigureAwait(false);
 1475
 1476        /// <summary>
 1477        /// Opens a stream for reading from the blob.  The stream will only download
 1478        /// the blob as the stream is read from.
 1479        /// </summary>
 1480        /// <param name="position">
 1481        /// The position within the blob to begin the stream.
 1482        /// Defaults to the beginning of the blob.
 1483        /// </param>
 1484        /// <param name="bufferSize">
 1485        /// The buffer size to use when the stream downloads parts
 1486        /// of the blob.  Defaults to 1 MB.
 1487        /// </param>
 1488        /// <param name="conditions">
 1489        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 1490        /// the download of the blob.
 1491        /// </param>
 1492        /// <param name="async">
 1493        /// Whether to invoke the operation asynchronously.
 1494        /// </param>
 1495        /// <param name="cancellationToken">
 1496        /// Optional <see cref="CancellationToken"/> to propagate
 1497        /// notifications that the operation should be cancelled.
 1498        /// </param>
 1499        /// <returns>
 1500        /// Returns a stream that will download the blob as the stream
 1501        /// is read from.
 1502        /// </returns>
 1503#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
 1504        internal async Task<Stream> OpenReadInternal(
 1505#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
 1506            long position,
 1507            int? bufferSize,
 1508            BlobRequestConditions conditions,
 1509#pragma warning disable CA1801
 1510            bool async,
 1511            CancellationToken cancellationToken)
 1512#pragma warning restore CA1801
 1513        {
 1481514            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 1515            {
 1516                Pipeline.LogMethodEnter(
 1517                nameof(BlobBaseClient),
 1518                message:
 1519                $"{nameof(position)}: {position}\n" +
 1520                $"{nameof(bufferSize)}: {bufferSize}\n" +
 1521                $"{nameof(conditions)}: {conditions}");
 1522
 1481523                DiagnosticScope scope = ClientDiagnostics.CreateScope($"{nameof(BlobBaseClient)}.{nameof(OpenRead)}");
 1524                try
 1525                {
 1481526                    scope.Start();
 1527
 1481528                    return new LazyLoadingReadOnlyStream<BlobRequestConditions, BlobProperties>(
 1481529                        async (HttpRange range,
 1481530                        BlobRequestConditions conditions,
 1481531                        bool rangeGetContentHash,
 1481532                        bool async,
 1481533                        CancellationToken cancellationToken) =>
 1481534                        {
 7241535                            Response<BlobDownloadInfo> response = await DownloadInternal(
 7241536                                range,
 7241537                                conditions,
 7241538                                rangeGetContentHash,
 7241539                                async,
 7241540                                cancellationToken).ConfigureAwait(false);
 1481541
 6841542                            return Response.FromValue(
 6841543                                (IDownloadedContent)response.Value,
 6841544                                response.GetRawResponse());
 6681545                        },
 4601546                        (ETag? eTag) => new BlobRequestConditions { IfMatch = eTag },
 1481547                        async (bool async, CancellationToken cancellationToken)
 1561548                            => await GetPropertiesInternal(conditions: default, async, cancellationToken).ConfigureAwait
 1481549                        position,
 1481550                        bufferSize,
 1481551                        conditions);
 1552                }
 01553                catch (Exception ex)
 1554                {
 01555                    scope.Failed(ex);
 1556                    Pipeline.LogException(ex);
 01557                    throw;
 1558                }
 1559                finally
 1560                {
 1481561                    scope.Dispose();
 1562                    Pipeline.LogMethodExit(nameof(BlobContainerClient));
 1563                }
 1564            }
 1481565        }
 1566
 1567        #endregion OpenRead
 1568
 1569        #region StartCopyFromUri
 1570        /// <summary>
 1571        /// The <see cref="StartCopyFromUri(Uri, BlobCopyFromUriOptions, CancellationToken)"/>
 1572        /// operation begins an asynchronous copy of the data from the <paramref name="source"/> to this blob.
 1573        /// You can check the <see cref="BlobProperties.CopyStatus"/>
 1574        /// returned from the <see cref="GetProperties"/> to determine if the
 1575        /// copy has completed.
 1576        ///
 1577        /// For more information, see
 1578        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob">
 1579        /// Copy Blob</see>.
 1580        /// </summary>
 1581        /// <param name="source">
 1582        /// Specifies the <see cref="Uri"/> of the source blob.  The value may
 1583        /// be a <see cref="Uri" /> of up to 2 KB in length that specifies a
 1584        /// blob.  A source blob in the same storage account can be
 1585        /// authenticated via Shared Key.  However, if the source is a blob in
 1586        /// another account, the source blob must either be public or must be
 1587        /// authenticated via a shared access signature. If the source blob
 1588        /// is public, no authentication is required to perform the copy
 1589        /// operation.
 1590        ///
 1591        /// The source object may be a file in the Azure File service.  If the
 1592        /// source object is a file that is to be copied to a blob, then the
 1593        /// source file must be authenticated using a shared access signature,
 1594        /// whether it resides in the same account or in a different account.
 1595        /// </param>
 1596        /// <param name="options">
 1597        /// Optional parameters.
 1598        /// </param>
 1599        /// <param name="cancellationToken">
 1600        /// Optional <see cref="CancellationToken"/> to propagate
 1601        /// notifications that the operation should be cancelled.
 1602        /// </param>
 1603        /// <returns>
 1604        /// A <see cref="CopyFromUriOperation"/> describing the
 1605        /// state of the copy operation.
 1606        /// </returns>
 1607        /// <remarks>
 1608        /// A <see cref="RequestFailedException"/> will be thrown if
 1609        /// a failure occurs.
 1610        /// </remarks>
 1611        public virtual CopyFromUriOperation StartCopyFromUri(
 1612            Uri source,
 1613            BlobCopyFromUriOptions options,
 1614            CancellationToken cancellationToken = default)
 1615        {
 601616            Response<BlobCopyInfo> response = StartCopyFromUriInternal(
 601617                source,
 601618                options?.Metadata,
 601619                options?.Tags,
 601620                options?.AccessTier,
 601621                options?.SourceConditions,
 601622                options?.DestinationConditions,
 601623                options?.RehydratePriority,
 601624                options?.ShouldSealDestination,
 601625                async: false,
 601626                cancellationToken)
 601627                .EnsureCompleted();
 361628            return new CopyFromUriOperation(
 361629                this,
 361630                response.Value.CopyId,
 361631                response.GetRawResponse(),
 361632                cancellationToken);
 1633        }
 1634
 1635        /// <summary>
 1636        /// The <see cref="StartCopyFromUri(Uri, Metadata, AccessTier?, BlobRequestConditions, BlobRequestConditions, Re
 1637        /// operation begins an asynchronous copy of the data from the <paramref name="source"/> to this blob.
 1638        /// You can check the <see cref="BlobProperties.CopyStatus"/>
 1639        /// returned from the <see cref="GetProperties"/> to determine if the
 1640        /// copy has completed.
 1641        ///
 1642        /// For more information, see
 1643        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob">
 1644        /// Copy Blob</see>.
 1645        /// </summary>
 1646        /// <param name="source">
 1647        /// Specifies the <see cref="Uri"/> of the source blob.  The value may
 1648        /// be a <see cref="Uri" /> of up to 2 KB in length that specifies a
 1649        /// blob.  A source blob in the same storage account can be
 1650        /// authenticated via Shared Key.  However, if the source is a blob in
 1651        /// another account, the source blob must either be public or must be
 1652        /// authenticated via a shared access signature. If the source blob
 1653        /// is public, no authentication is required to perform the copy
 1654        /// operation.
 1655        ///
 1656        /// The source object may be a file in the Azure File service.  If the
 1657        /// source object is a file that is to be copied to a blob, then the
 1658        /// source file must be authenticated using a shared access signature,
 1659        /// whether it resides in the same account or in a different account.
 1660        /// </param>
 1661        /// <param name="metadata">
 1662        /// Optional custom metadata to set for this blob.
 1663        /// </param>
 1664        /// <param name="accessTier">
 1665        /// Optional <see cref="AccessTier"/>
 1666        /// Indicates the tier to be set on the blob.
 1667        /// </param>
 1668        /// <param name="sourceConditions">
 1669        /// Optional <see cref="BlobRequestConditions"/> to add
 1670        /// conditions on the copying of data from this source blob.
 1671        /// </param>
 1672        /// <param name="destinationConditions">
 1673        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 1674        /// the copying of data to this blob.
 1675        /// </param>
 1676        /// <param name="rehydratePriority">
 1677        /// Optional <see cref="RehydratePriority"/>
 1678        /// Indicates the priority with which to rehydrate an archived blob.
 1679        /// </param>
 1680        /// <param name="cancellationToken">
 1681        /// Optional <see cref="CancellationToken"/> to propagate
 1682        /// notifications that the operation should be cancelled.
 1683        /// </param>
 1684        /// <returns>
 1685        /// A <see cref="CopyFromUriOperation"/> describing the
 1686        /// state of the copy operation.
 1687        /// </returns>
 1688        /// <remarks>
 1689        /// A <see cref="RequestFailedException"/> will be thrown if
 1690        /// a failure occurs.
 1691        /// </remarks>
 1692        [EditorBrowsable(EditorBrowsableState.Never)]
 1693        public virtual CopyFromUriOperation StartCopyFromUri(
 1694            Uri source,
 1695            Metadata metadata = default,
 1696            AccessTier? accessTier = default,
 1697            BlobRequestConditions sourceConditions = default,
 1698            BlobRequestConditions destinationConditions = default,
 1699            RehydratePriority? rehydratePriority = default,
 1700            CancellationToken cancellationToken = default)
 1701        {
 161702            Response<BlobCopyInfo> response = StartCopyFromUriInternal(
 161703                source,
 161704                metadata,
 161705                default,
 161706                accessTier,
 161707                sourceConditions,
 161708                destinationConditions,
 161709                rehydratePriority,
 161710                sealBlob: default,
 161711                async: false,
 161712                cancellationToken)
 161713                .EnsureCompleted();
 121714            return new CopyFromUriOperation(
 121715                this,
 121716                response.Value.CopyId,
 121717                response.GetRawResponse(),
 121718                cancellationToken);
 1719        }
 1720
 1721        /// <summary>
 1722        /// The <see cref="StartCopyFromUri(Uri, Metadata, AccessTier?, BlobRequestConditions, BlobRequestConditions, Re
 1723        /// operation begins an asynchronous copy of the data from the <paramref name="source"/>
 1724        /// to this blob.  You can check the <see cref="BlobProperties.CopyStatus"/>
 1725        /// returned from the <see cref="GetPropertiesAsync"/> to determine if
 1726        /// the copy has completed.
 1727        ///
 1728        /// For more information, see
 1729        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob">
 1730        /// Copy Blob</see>.
 1731        /// </summary>
 1732        /// <param name="source">
 1733        /// Specifies the <see cref="Uri"/> of the source blob.  The value may
 1734        /// be a <see cref="Uri" /> of up to 2 KB in length that specifies a
 1735        /// blob.  A source blob in the same storage account can be
 1736        /// authenticated via Shared Key.  However, if the source is a blob in
 1737        /// another account, the source blob must either be public or must be
 1738        /// authenticated via a shared access signature. If the source blob
 1739        /// is public, no authentication is required to perform the copy
 1740        /// operation.
 1741        ///
 1742        /// The source object may be a file in the Azure File service.  If the
 1743        /// source object is a file that is to be copied to a blob, then the
 1744        /// source file must be authenticated using a shared access signature,
 1745        /// whether it resides in the same account or in a different account.
 1746        /// </param>
 1747        /// <param name="options">
 1748        /// Optional parameters.
 1749        /// </param>
 1750        /// <param name="cancellationToken">
 1751        /// Optional <see cref="CancellationToken"/> to propagate
 1752        /// notifications that the operation should be cancelled.
 1753        /// </param>
 1754        /// <returns>
 1755        /// A <see cref="CopyFromUriOperation"/> describing the
 1756        /// state of the copy operation.
 1757        /// </returns>
 1758        /// <remarks>
 1759        /// A <see cref="RequestFailedException"/> will be thrown if
 1760        /// a failure occurs.
 1761        /// </remarks>
 1762        public virtual async Task<CopyFromUriOperation> StartCopyFromUriAsync(
 1763            Uri source,
 1764            BlobCopyFromUriOptions options,
 1765            CancellationToken cancellationToken = default)
 1766        {
 601767            Response<BlobCopyInfo> response = await StartCopyFromUriInternal(
 601768                source,
 601769                options?.Metadata,
 601770                options?.Tags,
 601771                options?.AccessTier,
 601772                options?.SourceConditions,
 601773                options?.DestinationConditions,
 601774                options?.RehydratePriority,
 601775                options?.ShouldSealDestination,
 601776                async: true,
 601777                cancellationToken)
 601778                .ConfigureAwait(false);
 361779            return new CopyFromUriOperation(
 361780                this,
 361781                response.Value.CopyId,
 361782                response.GetRawResponse(),
 361783                cancellationToken);
 361784        }
 1785
 1786        /// <summary>
 1787        /// The <see cref="StartCopyFromUri(Uri, Metadata, AccessTier?, BlobRequestConditions, BlobRequestConditions, Re
 1788        /// operation begins an asynchronous copy of the data from the <paramref name="source"/>
 1789        /// to this blob.You can check the <see cref="BlobProperties.CopyStatus"/>
 1790        /// returned from the <see cref="GetPropertiesAsync"/> to determine if
 1791        /// the copy has completed.
 1792        ///
 1793        /// For more information, see
 1794        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob">
 1795        /// Copy Blob</see>.
 1796        /// </summary>
 1797        /// <param name="source">
 1798        /// Specifies the <see cref="Uri"/> of the source blob.  The value may
 1799        /// be a <see cref="Uri" /> of up to 2 KB in length that specifies a
 1800        /// blob.  A source blob in the same storage account can be
 1801        /// authenticated via Shared Key.  However, if the source is a blob in
 1802        /// another account, the source blob must either be public or must be
 1803        /// authenticated via a shared access signature. If the source blob
 1804        /// is public, no authentication is required to perform the copy
 1805        /// operation.
 1806        ///
 1807        /// The source object may be a file in the Azure File service.  If the
 1808        /// source object is a file that is to be copied to a blob, then the
 1809        /// source file must be authenticated using a shared access signature,
 1810        /// whether it resides in the same account or in a different account.
 1811        /// </param>
 1812        /// <param name="metadata">
 1813        /// Optional custom metadata to set for this blob.
 1814        /// </param>
 1815        /// <param name="accessTier">
 1816        /// Optional <see cref="AccessTier"/>
 1817        /// Indicates the tier to be set on the blob.
 1818        /// </param>
 1819        /// <param name="sourceConditions">
 1820        /// Optional <see cref="BlobRequestConditions"/> to add
 1821        /// conditions on the copying of data from this source blob.
 1822        /// </param>
 1823        /// <param name="destinationConditions">
 1824        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 1825        /// the copying of data to this blob.
 1826        /// </param>
 1827        /// <param name="rehydratePriority">
 1828        /// Optional <see cref="RehydratePriority"/>
 1829        /// Indicates the priority with which to rehydrate an archived blob.
 1830        /// </param>
 1831        /// <param name="cancellationToken">
 1832        /// Optional <see cref="CancellationToken"/> to propagate
 1833        /// notifications that the operation should be cancelled.
 1834        /// </param>
 1835        /// <returns>
 1836        /// A <see cref="CopyFromUriOperation"/> describing the
 1837        /// state of the copy operation.
 1838        /// </returns>
 1839        /// <remarks>
 1840        /// A <see cref="RequestFailedException"/> will be thrown if
 1841        /// a failure occurs.
 1842        /// </remarks>
 1843        [EditorBrowsable(EditorBrowsableState.Never)]
 1844        public virtual async Task<CopyFromUriOperation> StartCopyFromUriAsync(
 1845            Uri source,
 1846            Metadata metadata = default,
 1847            AccessTier? accessTier = default,
 1848            BlobRequestConditions sourceConditions = default,
 1849            BlobRequestConditions destinationConditions = default,
 1850            RehydratePriority? rehydratePriority = default,
 1851            CancellationToken cancellationToken = default)
 1852        {
 161853            Response<BlobCopyInfo> response = await StartCopyFromUriInternal(
 161854                source,
 161855                metadata,
 161856                default,
 161857                accessTier,
 161858                sourceConditions,
 161859                destinationConditions,
 161860                rehydratePriority,
 161861                sealBlob: default,
 161862                async: true,
 161863                cancellationToken)
 161864                .ConfigureAwait(false);
 121865            return new CopyFromUriOperation(
 121866                this,
 121867                response.Value.CopyId,
 121868                response.GetRawResponse(),
 121869                cancellationToken);
 121870        }
 1871
 1872        /// <summary>
 1873        /// The <see cref="StartCopyFromUriInternal"/> operation begins an
 1874        /// asynchronous copy of the data from the <paramref name="source"/>
 1875        /// to this blob.  You can check <see cref="BlobProperties.CopyStatus"/>
 1876        /// returned from the<see cref="GetPropertiesAsync"/> to determine if
 1877        /// the copy has completed.
 1878        ///
 1879        /// For more information, see
 1880        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob">
 1881        /// Copy Blob</see>.
 1882        /// </summary>
 1883        /// <param name="source">
 1884        /// Specifies the <see cref="Uri"/> of the source blob.  The value may
 1885        /// be a <see cref="Uri" /> of up to 2 KB in length that specifies a
 1886        /// blob.  A source blob in the same storage account can be
 1887        /// authenticated via Shared Key.  However, if the source is a blob in
 1888        /// another account, the source blob must either be public or must be
 1889        /// authenticated via a shared access signature. If the source blob
 1890        /// is public, no authentication is required to perform the copy
 1891        /// operation.
 1892        ///
 1893        /// The source object may be a file in the Azure File service.  If the
 1894        /// source object is a file that is to be copied to a blob, then the
 1895        /// source file must be authenticated using a shared access signature,
 1896        /// whether it resides in the same account or in a different account.
 1897        /// </param>
 1898        /// <param name="metadata">
 1899        /// Optional custom metadata to set for this blob.
 1900        /// </param>
 1901        /// <param name="tags">
 1902        /// Optional tags to set for this blob.
 1903        /// </param>
 1904        /// <param name="accessTier">
 1905        /// Optional <see cref="AccessTier"/>
 1906        /// Indicates the tier to be set on the blob.
 1907        /// </param>
 1908        /// <param name="sourceConditions">
 1909        /// Optional <see cref="BlobRequestConditions"/> to add
 1910        /// conditions on the copying of data from this source blob.
 1911        /// </param>
 1912        /// <param name="destinationConditions">
 1913        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 1914        /// the copying of data to this blob.
 1915        /// </param>
 1916        /// <param name="rehydratePriority">
 1917        /// Optional <see cref="RehydratePriority"/>
 1918        /// Indicates the priority with which to rehydrate an archived blob.
 1919        /// </param>
 1920        /// <param name="sealBlob">
 1921        /// If the destination blob should be sealed.
 1922        /// Only applicable for Append Blobs.
 1923        /// </param>
 1924        /// <param name="async">
 1925        /// Whether to invoke the operation asynchronously.
 1926        /// </param>
 1927        /// <param name="cancellationToken">
 1928        /// Optional <see cref="CancellationToken"/> to propagate
 1929        /// notifications that the operation should be cancelled.
 1930        /// </param>
 1931        /// <returns>
 1932        /// A <see cref="Response{BlobCopyInfo}"/> describing the
 1933        /// state of the copy operation.
 1934        /// </returns>
 1935        /// <remarks>
 1936        /// A <see cref="RequestFailedException"/> will be thrown if
 1937        /// a failure occurs.
 1938        /// </remarks>
 1939        private async Task<Response<BlobCopyInfo>> StartCopyFromUriInternal(
 1940            Uri source,
 1941            Metadata metadata,
 1942            Tags tags,
 1943            AccessTier? accessTier,
 1944            BlobRequestConditions sourceConditions,
 1945            BlobRequestConditions destinationConditions,
 1946            RehydratePriority? rehydratePriority,
 1947            bool? sealBlob,
 1948            bool async,
 1949            CancellationToken cancellationToken)
 1950        {
 1521951            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 1952            {
 1953                Pipeline.LogMethodEnter(
 1954                    nameof(BlobBaseClient),
 1955                    message:
 1956                    $"{nameof(Uri)}: {Uri}\n" +
 1957                    $"{nameof(source)}: {source}\n" +
 1958                    $"{nameof(sourceConditions)}: {sourceConditions}\n" +
 1959                    $"{nameof(destinationConditions)}: {destinationConditions}");
 1960                try
 1961                {
 1521962                    return await BlobRestClient.Blob.StartCopyFromUriAsync(
 1521963                        ClientDiagnostics,
 1521964                        Pipeline,
 1521965                        Uri,
 1521966                        copySource: source,
 1521967                        version: Version.ToVersionString(),
 1521968                        rehydratePriority: rehydratePriority,
 1521969                        tier: accessTier,
 1521970                        sourceIfModifiedSince: sourceConditions?.IfModifiedSince,
 1521971                        sourceIfUnmodifiedSince: sourceConditions?.IfUnmodifiedSince,
 1521972                        sourceIfMatch: sourceConditions?.IfMatch,
 1521973                        sourceIfNoneMatch: sourceConditions?.IfNoneMatch,
 1521974                        sourceIfTags: sourceConditions?.TagConditions,
 1521975                        ifModifiedSince: destinationConditions?.IfModifiedSince,
 1521976                        ifUnmodifiedSince: destinationConditions?.IfUnmodifiedSince,
 1521977                        ifMatch: destinationConditions?.IfMatch,
 1521978                        ifNoneMatch: destinationConditions?.IfNoneMatch,
 1521979                        leaseId: destinationConditions?.LeaseId,
 1521980                        ifTags: destinationConditions?.TagConditions,
 1521981                        metadata: metadata,
 1521982                        blobTagsString: tags?.ToTagsString(),
 1521983                        sealBlob: sealBlob,
 1521984                        async: async,
 1521985                        operationName: $"{nameof(BlobBaseClient)}.{nameof(StartCopyFromUri)}",
 1521986                        cancellationToken: cancellationToken)
 1521987                        .ConfigureAwait(false);
 1988                }
 561989                catch (Exception ex)
 1990                {
 1991                    Pipeline.LogException(ex);
 561992                    throw;
 1993                }
 1994                finally
 1995                {
 1996                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 1997                }
 1998            }
 961999        }
 2000        #endregion StartCopyFromUri
 2001
 2002        #region AbortCopyFromUri
 2003        /// <summary>
 2004        /// The <see cref="AbortCopyFromUri"/> operation aborts a pending
 2005        /// <see cref="CopyFromUriOperation"/>, and leaves a this
 2006        /// blob with zero length and full metadata.
 2007        ///
 2008        /// For more information, see
 2009        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/abort-copy-blob">
 2010        /// Abort Copy Blob</see>.
 2011        /// </summary>
 2012        /// <param name="copyId">
 2013        /// ID of the copy operation to abort.
 2014        /// </param>
 2015        /// <param name="conditions">
 2016        /// Optional <see cref="BlobRequestConditions"/> to add
 2017        /// conditions on aborting the copy operation.
 2018        /// </param>
 2019        /// <param name="cancellationToken">
 2020        /// Optional <see cref="CancellationToken"/> to propagate
 2021        /// notifications that the operation should be cancelled.
 2022        /// </param>
 2023        /// <returns>
 2024        /// A <see cref="Response"/> on successfully aborting.
 2025        /// </returns>
 2026        /// <remarks>
 2027        /// A <see cref="RequestFailedException"/> will be thrown if
 2028        /// a failure occurs.
 2029        /// </remarks>
 2030        public virtual Response AbortCopyFromUri(
 2031            string copyId,
 2032            BlobRequestConditions conditions = default,
 2033            CancellationToken cancellationToken = default) =>
 82034            AbortCopyFromUriInternal(
 82035                copyId,
 82036                conditions,
 82037                false, // async
 82038                cancellationToken)
 82039                .EnsureCompleted();
 2040
 2041        /// <summary>
 2042        /// The <see cref="AbortCopyFromUriAsync"/> operation aborts a pending
 2043        /// <see cref="CopyFromUriOperation"/>, and leaves a this
 2044        /// blob with zero length and full metadata.
 2045        ///
 2046        /// For more information, see
 2047        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/abort-copy-blob">
 2048        /// Abort Copy Blob</see>.
 2049        /// </summary>
 2050        /// <param name="copyId">
 2051        /// ID of the copy operation to abort.
 2052        /// </param>
 2053        /// <param name="conditions">
 2054        /// Optional <see cref="BlobRequestConditions"/> to add
 2055        /// conditions on aborting the copy operation.
 2056        /// </param>
 2057        /// <param name="cancellationToken">
 2058        /// Optional <see cref="CancellationToken"/> to propagate
 2059        /// notifications that the operation should be cancelled.
 2060        /// </param>
 2061        /// <returns>
 2062        /// A <see cref="Response"/> on successfully aborting.
 2063        /// </returns>
 2064        /// <remarks>
 2065        /// A <see cref="RequestFailedException"/> will be thrown if
 2066        /// a failure occurs.
 2067        /// </remarks>
 2068        public virtual async Task<Response> AbortCopyFromUriAsync(
 2069            string copyId,
 2070            BlobRequestConditions conditions = default,
 2071            CancellationToken cancellationToken = default) =>
 82072            await AbortCopyFromUriInternal(
 82073                copyId,
 82074                conditions,
 82075                true, // async
 82076                cancellationToken)
 82077                .ConfigureAwait(false);
 2078
 2079        /// <summary>
 2080        /// The <see cref="AbortCopyFromUriAsync"/> operation aborts a pending
 2081        /// <see cref="CopyFromUriOperation"/>, and leaves a this
 2082        /// blob with zero length and full metadata.
 2083        ///
 2084        /// For more information, see
 2085        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/abort-copy-blob">
 2086        /// Abort Copy Blob</see>.
 2087        /// </summary>
 2088        /// <param name="copyId">
 2089        /// ID of the copy operation to abort.
 2090        /// </param>
 2091        /// <param name="conditions">
 2092        /// Optional <see cref="BlobRequestConditions"/> to add
 2093        /// conditions on aborting the copy operation.
 2094        /// </param>
 2095        /// <param name="async">
 2096        /// Whether to invoke the operation asynchronously.
 2097        /// </param>
 2098        /// <param name="cancellationToken">
 2099        /// Optional <see cref="CancellationToken"/> to propagate
 2100        /// notifications that the operation should be cancelled.
 2101        /// </param>
 2102        /// <returns>
 2103        /// A <see cref="Response"/> on successfully aborting.
 2104        /// </returns>
 2105        /// <remarks>
 2106        /// A <see cref="RequestFailedException"/> will be thrown if
 2107        /// a failure occurs.
 2108        /// </remarks>
 2109        private async Task<Response> AbortCopyFromUriInternal(
 2110            string copyId,
 2111            BlobRequestConditions conditions,
 2112            bool async,
 2113            CancellationToken cancellationToken)
 2114        {
 162115            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 2116            {
 2117                Pipeline.LogMethodEnter(
 2118                    nameof(BlobBaseClient),
 2119                    message:
 2120                    $"{nameof(Uri)}: {Uri}\n" +
 2121                    $"{nameof(copyId)}: {copyId}\n" +
 2122                    $"{nameof(conditions)}: {conditions}");
 2123                try
 2124                {
 162125                    return await BlobRestClient.Blob.AbortCopyFromUriAsync(
 162126                        ClientDiagnostics,
 162127                        Pipeline,
 162128                        Uri,
 162129                        copyId: copyId,
 162130                        version: Version.ToVersionString(),
 162131                        leaseId: conditions?.LeaseId,
 162132                        async: async,
 162133                        operationName: "BlobBaseClient.AbortCopyFromUri",
 162134                        cancellationToken: cancellationToken)
 162135                        .ConfigureAwait(false);
 2136                }
 82137                catch (Exception ex)
 2138                {
 2139                    Pipeline.LogException(ex);
 82140                    throw;
 2141                }
 2142                finally
 2143                {
 2144                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 2145                }
 2146            }
 82147        }
 2148        #endregion AbortCopyFromUri
 2149
 2150        #region CopyFromUri
 2151        /// <summary>
 2152        /// The Copy Blob From URL operation copies a blob to a destination within the storage account synchronously
 2153        /// for source blob sizes up to 256 MB. This API is available starting in version 2018-03-28.
 2154        /// The source for a Copy Blob From URL operation can be any committed block blob in any Azure storage account
 2155        /// which is either public or authorized with a shared access signature.
 2156        ///
 2157        /// The size of the source blob can be a maximum length of up to 256 MB.
 2158        ///
 2159        /// For more information, see
 2160        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob-from-url">
 2161        /// Copy Blob From URL</see>.
 2162        /// </summary>
 2163        /// <param name="source">
 2164        /// Required. Specifies the URL of the source blob. The value may be a URL of up to 2 KB in length
 2165        /// that specifies a blob. The value should be URL-encoded as it would appear in a request URI. The
 2166        /// source blob must either be public or must be authorized via a shared access signature. If the
 2167        /// source blob is public, no authorization is required to perform the operation. If the size of the
 2168        /// source blob is greater than 256 MB, the request will fail with 409 (Conflict). The blob type of
 2169        /// the source blob has to be block blob.
 2170        /// </param>
 2171        /// <param name="options">
 2172        /// Optional parameters.
 2173        /// </param>
 2174        /// <param name="cancellationToken">
 2175        /// Optional <see cref="CancellationToken"/> to propagate
 2176        /// notifications that the operation should be cancelled.
 2177        /// </param>
 2178        /// <returns>
 2179        /// A <see cref="Response{BlobCopyInfo}"/> describing the
 2180        /// state of the copy operation.
 2181        /// </returns>
 2182        /// <remarks>
 2183        /// A <see cref="RequestFailedException"/> will be thrown if
 2184        /// a failure occurs.
 2185        /// </remarks>
 2186        public virtual Response<BlobCopyInfo> SyncCopyFromUri(
 2187            Uri source,
 2188            BlobCopyFromUriOptions options = default,
 2189            CancellationToken cancellationToken = default)
 562190            => SyncCopyFromUriInternal(
 562191                source: source,
 562192                metadata: options?.Metadata,
 562193                tags: options?.Tags,
 562194                accessTier: options?.AccessTier,
 562195                sourceConditions: options?.SourceConditions,
 562196                destinationConditions: options?.DestinationConditions,
 562197                async: false,
 562198                cancellationToken: cancellationToken)
 562199            .EnsureCompleted();
 2200
 2201        /// <summary>
 2202        /// The Copy Blob From URL operation copies a blob to a destination within the storage account synchronously
 2203        /// for source blob sizes up to 256 MB. This API is available starting in version 2018-03-28.
 2204        /// The source for a Copy Blob From URL operation can be any committed block blob in any Azure storage account
 2205        /// which is either public or authorized with a shared access signature.
 2206        ///
 2207        /// The size of the source blob can be a maximum length of up to 256 MB.
 2208        ///
 2209        /// For more information, see
 2210        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob-from-url">
 2211        /// Copy Blob From URL</see>.
 2212        /// </summary>
 2213        /// <param name="source">
 2214        /// Required. Specifies the URL of the source blob. The value may be a URL of up to 2 KB in length
 2215        /// that specifies a blob. The value should be URL-encoded as it would appear in a request URI. The
 2216        /// source blob must either be public or must be authorized via a shared access signature. If the
 2217        /// source blob is public, no authorization is required to perform the operation. If the size of the
 2218        /// source blob is greater than 256 MB, the request will fail with 409 (Conflict). The blob type of
 2219        /// the source blob has to be block blob.
 2220        /// </param>
 2221        /// <param name="options">
 2222        /// Optional parameters.
 2223        /// </param>
 2224        /// <param name="cancellationToken">
 2225        /// Optional <see cref="CancellationToken"/> to propagate
 2226        /// notifications that the operation should be cancelled.
 2227        /// </param>
 2228        /// <returns>
 2229        /// A <see cref="Response{BlobCopyInfo}"/> describing the
 2230        /// state of the copy operation.
 2231        /// </returns>
 2232        /// <remarks>
 2233        /// A <see cref="RequestFailedException"/> will be thrown if
 2234        /// a failure occurs.
 2235        /// </remarks>
 2236        public virtual async Task<Response<BlobCopyInfo>> SyncCopyFromUriAsync(
 2237            Uri source,
 2238            BlobCopyFromUriOptions options = default,
 2239            CancellationToken cancellationToken = default)
 562240            => await SyncCopyFromUriInternal(
 562241                source: source,
 562242                metadata: options?.Metadata,
 562243                tags: options?.Tags,
 562244                accessTier: options?.AccessTier,
 562245                sourceConditions: options?.SourceConditions,
 562246                destinationConditions: options?.DestinationConditions,
 562247                async: true,
 562248                cancellationToken: cancellationToken)
 562249            .ConfigureAwait(false);
 2250
 2251        /// <summary>
 2252        /// The Copy Blob From URL operation copies a blob to a destination within the storage account synchronously
 2253        /// for source blob sizes up to 256 MB. This API is available starting in version 2018-03-28.
 2254        /// The source for a Copy Blob From URL operation can be any committed block blob in any Azure storage account
 2255        /// which is either public or authorized with a shared access signature.
 2256        ///
 2257        /// The size of the source blob can be a maximum length of up to 256 MB.
 2258        ///
 2259        /// For more information, see
 2260        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob-from-url">
 2261        /// Copy Blob From URL</see>.
 2262        /// </summary>
 2263        /// <param name="source">
 2264        /// Required. Specifies the URL of the source blob. The value may be a URL of up to 2 KB in length
 2265        /// that specifies a blob. The value should be URL-encoded as it would appear in a request URI. The
 2266        /// source blob must either be public or must be authorized via a shared access signature. If the
 2267        /// source blob is public, no authorization is required to perform the operation. If the size of the
 2268        /// source blob is greater than 256 MB, the request will fail with 409 (Conflict). The blob type of
 2269        /// the source blob has to be block blob.
 2270        /// </param>
 2271        /// <param name="metadata">
 2272        /// Optional custom metadata to set for this blob.
 2273        /// </param>
 2274        /// <param name="tags">
 2275        /// Optional tags to set for this blob.
 2276        /// </param>
 2277        /// <param name="accessTier">
 2278        /// Optional <see cref="AccessTier"/>
 2279        /// Indicates the tier to be set on the blob.
 2280        /// </param>
 2281        /// <param name="sourceConditions">
 2282        /// Optional <see cref="BlobRequestConditions"/> to add
 2283        /// conditions on the copying of data from this source blob.
 2284        /// </param>
 2285        /// <param name="destinationConditions">
 2286        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 2287        /// the copying of data to this blob.
 2288        /// </param>
 2289        /// <param name="async">
 2290        /// Whether to invoke the operation asynchronously.
 2291        /// </param>
 2292        /// <param name="cancellationToken">
 2293        /// Optional <see cref="CancellationToken"/> to propagate
 2294        /// notifications that the operation should be cancelled.
 2295        /// </param>
 2296        /// <returns>
 2297        /// A <see cref="Response{BlobCopyInfo}"/> describing the
 2298        /// state of the copy operation.
 2299        /// </returns>
 2300        /// <remarks>
 2301        /// A <see cref="RequestFailedException"/> will be thrown if
 2302        /// a failure occurs.
 2303        /// </remarks>
 2304        private async Task<Response<BlobCopyInfo>> SyncCopyFromUriInternal(
 2305            Uri source,
 2306            Metadata metadata,
 2307            Tags tags,
 2308            AccessTier? accessTier,
 2309            BlobRequestConditions sourceConditions,
 2310            BlobRequestConditions destinationConditions,
 2311            bool async,
 2312            CancellationToken cancellationToken)
 2313        {
 1122314            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 2315            {
 2316                try
 2317                {
 2318                    Pipeline.LogMethodEnter(
 2319                    nameof(BlobBaseClient),
 2320                    message:
 2321                    $"{nameof(Uri)}: {Uri}\n" +
 2322                    $"{nameof(source)}: {source}\n" +
 2323                    $"{nameof(sourceConditions)}: {sourceConditions}\n" +
 2324                    $"{nameof(destinationConditions)}: {destinationConditions}");
 2325
 1122326                    return await BlobRestClient.Blob.CopyFromUriAsync(
 1122327                        clientDiagnostics: ClientDiagnostics,
 1122328                        pipeline: Pipeline,
 1122329                        resourceUri: Uri,
 1122330                        copySource: source,
 1122331                        version: Version.ToVersionString(),
 1122332                        tier: accessTier,
 1122333                        sourceIfModifiedSince: sourceConditions?.IfModifiedSince,
 1122334                        sourceIfUnmodifiedSince: sourceConditions?.IfUnmodifiedSince,
 1122335                        sourceIfMatch: sourceConditions?.IfMatch,
 1122336                        sourceIfNoneMatch: sourceConditions?.IfNoneMatch,
 1122337                        ifModifiedSince: destinationConditions?.IfModifiedSince,
 1122338                        ifUnmodifiedSince: destinationConditions?.IfUnmodifiedSince,
 1122339                        ifMatch: destinationConditions?.IfMatch,
 1122340                        ifNoneMatch: destinationConditions?.IfNoneMatch,
 1122341                        ifTags: destinationConditions?.TagConditions,
 1122342                        leaseId: destinationConditions?.LeaseId,
 1122343                        metadata: metadata,
 1122344                        blobTagsString: tags?.ToTagsString(),
 1122345                        async: async,
 1122346                        operationName: $"{nameof(BlobBaseClient)}.{nameof(SyncCopyFromUri)}",
 1122347                        cancellationToken: cancellationToken)
 1122348                        .ConfigureAwait(false);
 2349                }
 482350                catch (Exception ex)
 2351                {
 2352                    Pipeline.LogException(ex);
 482353                    throw;
 2354                }
 2355                finally
 2356                {
 2357                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 2358                }
 2359            }
 642360        }
 2361        #endregion CopyFromUri
 2362
 2363        #region Delete
 2364        /// <summary>
 2365        /// The <see cref="Delete"/> operation marks the specified blob
 2366        /// or snapshot for  deletion. The blob is later deleted during
 2367        /// garbage collection.
 2368        ///
 2369        /// Note that in order to delete a blob, you must delete all of its
 2370        /// snapshots. You can delete both at the same time using
 2371        /// <see cref="DeleteSnapshotsOption.IncludeSnapshots"/>.
 2372        ///
 2373        /// For more information, see
 2374        /// <see href="https://docs.microsoft.com/rest/api/storageservices/delete-blob">
 2375        /// Delete Blob</see>.
 2376        /// </summary>
 2377        /// <param name="snapshotsOption">
 2378        /// Specifies options for deleting blob snapshots.
 2379        /// </param>
 2380        /// <param name="conditions">
 2381        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 2382        /// deleting this blob.
 2383        /// </param>
 2384        /// <param name="cancellationToken">
 2385        /// Optional <see cref="CancellationToken"/> to propagate
 2386        /// notifications that the operation should be cancelled.
 2387        /// </param>
 2388        /// <returns>
 2389        /// A <see cref="Response"/> on successfully deleting.
 2390        /// </returns>
 2391        /// <remarks>
 2392        /// A <see cref="RequestFailedException"/> will be thrown if
 2393        /// a failure occurs.
 2394        /// </remarks>
 2395        public virtual Response Delete(
 2396            DeleteSnapshotsOption snapshotsOption = default,
 2397            BlobRequestConditions conditions = default,
 2398            CancellationToken cancellationToken = default) =>
 422399            DeleteInternal(
 422400                snapshotsOption,
 422401                conditions,
 422402                false, // async
 422403                cancellationToken)
 422404                .EnsureCompleted();
 2405
 2406        /// <summary>
 2407        /// The <see cref="DeleteAsync"/> operation marks the specified blob
 2408        /// or snapshot for  deletion. The blob is later deleted during
 2409        /// garbage collection.
 2410        ///
 2411        /// Note that in order to delete a blob, you must delete all of its
 2412        /// snapshots. You can delete both at the same time using
 2413        /// <see cref="DeleteSnapshotsOption.IncludeSnapshots"/>.
 2414        ///
 2415        /// For more information, see
 2416        /// <see href="https://docs.microsoft.com/rest/api/storageservices/delete-blob">
 2417        /// Delete Blob</see>.
 2418        /// </summary>
 2419        /// <param name="snapshotsOption">
 2420        /// Specifies options for deleting blob snapshots.
 2421        /// </param>
 2422        /// <param name="conditions">
 2423        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 2424        /// deleting this blob.
 2425        /// </param>
 2426        /// <param name="cancellationToken">
 2427        /// Optional <see cref="CancellationToken"/> to propagate
 2428        /// notifications that the operation should be cancelled.
 2429        /// </param>
 2430        /// <returns>
 2431        /// A <see cref="Response"/> on successfully deleting.
 2432        /// </returns>
 2433        /// <remarks>
 2434        /// A <see cref="RequestFailedException"/> will be thrown if
 2435        /// a failure occurs.
 2436        /// </remarks>
 2437        public virtual async Task<Response> DeleteAsync(
 2438            DeleteSnapshotsOption snapshotsOption = default,
 2439            BlobRequestConditions conditions = default,
 2440            CancellationToken cancellationToken = default) =>
 1062441            await DeleteInternal(
 1062442                snapshotsOption,
 1062443                conditions,
 1062444                true, // async
 1062445                cancellationToken)
 1062446                .ConfigureAwait(false);
 2447
 2448        /// <summary>
 2449        /// The <see cref="DeleteIfExists"/> operation marks the specified blob
 2450        /// or snapshot for deletion, if the blob exists. The blob is later deleted
 2451        /// during garbage collection.
 2452        ///
 2453        /// Note that in order to delete a blob, you must delete all of its
 2454        /// snapshots. You can delete both at the same time using
 2455        /// <see cref="DeleteSnapshotsOption.IncludeSnapshots"/>.
 2456        ///
 2457        /// For more information, see
 2458        /// <see href="https://docs.microsoft.com/rest/api/storageservices/delete-blob">
 2459        /// Delete Blob</see>.
 2460        /// </summary>
 2461        /// <param name="snapshotsOption">
 2462        /// Specifies options for deleting blob snapshots.
 2463        /// </param>
 2464        /// <param name="conditions">
 2465        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 2466        /// deleting this blob.
 2467        /// </param>
 2468        /// <param name="cancellationToken">
 2469        /// Optional <see cref="CancellationToken"/> to propagate
 2470        /// notifications that the operation should be cancelled.
 2471        /// </param>
 2472        /// <returns>
 2473        /// A <see cref="Response"/> on successfully deleting.
 2474        /// </returns>
 2475        /// <remarks>
 2476        /// A <see cref="RequestFailedException"/> will be thrown if
 2477        /// a failure occurs.
 2478        /// </remarks>
 2479        public virtual Response<bool> DeleteIfExists(
 2480            DeleteSnapshotsOption snapshotsOption = default,
 2481            BlobRequestConditions conditions = default,
 2482            CancellationToken cancellationToken = default) =>
 142483            DeleteIfExistsInternal(
 142484                snapshotsOption,
 142485                conditions ?? default,
 142486                false, // async
 142487                cancellationToken)
 142488                .EnsureCompleted();
 2489
 2490        /// <summary>
 2491        /// The <see cref="DeleteIfExistsAsync"/> operation marks the specified blob
 2492        /// or snapshot for deletion, if the blob exists. The blob is later deleted
 2493        /// during garbage collection.
 2494        ///
 2495        /// Note that in order to delete a blob, you must delete all of its
 2496        /// snapshots. You can delete both at the same time using
 2497        /// <see cref="DeleteSnapshotsOption.IncludeSnapshots"/>.
 2498        ///
 2499        /// For more information, see
 2500        /// <see href="https://docs.microsoft.com/rest/api/storageservices/delete-blob">
 2501        /// Delete Blob</see>.
 2502        /// </summary>
 2503        /// <param name="snapshotsOption">
 2504        /// Specifies options for deleting blob snapshots.
 2505        /// </param>
 2506        /// <param name="conditions">
 2507        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 2508        /// deleting this blob.
 2509        /// </param>
 2510        /// <param name="cancellationToken">
 2511        /// Optional <see cref="CancellationToken"/> to propagate
 2512        /// notifications that the operation should be cancelled.
 2513        /// </param>
 2514        /// <returns>
 2515        /// A <see cref="Response"/> on successfully deleting.
 2516        /// </returns>
 2517        /// <remarks>
 2518        /// A <see cref="RequestFailedException"/> will be thrown if
 2519        /// a failure occurs.
 2520        /// </remarks>
 2521        public virtual async Task<Response<bool>> DeleteIfExistsAsync(
 2522            DeleteSnapshotsOption snapshotsOption = default,
 2523            BlobRequestConditions conditions = default,
 2524            CancellationToken cancellationToken = default) =>
 142525            await DeleteIfExistsInternal(
 142526                snapshotsOption,
 142527                conditions ?? default,
 142528                true, // async
 142529                cancellationToken)
 142530                .ConfigureAwait(false);
 2531
 2532        /// <summary>
 2533        /// The <see cref="DeleteIfExistsInternal"/> operation marks the specified blob
 2534        /// or snapshot for deletion, if the blob exists. The blob is later deleted
 2535        /// during garbage collection.
 2536        ///
 2537        /// Note that in order to delete a blob, you must delete all of its
 2538        /// snapshots. You can delete both at the same time using
 2539        /// <see cref="DeleteSnapshotsOption.IncludeSnapshots"/>.
 2540        ///
 2541        /// For more information, see
 2542        /// <see href="https://docs.microsoft.com/rest/api/storageservices/delete-blob">
 2543        /// Delete Blob</see>.
 2544        /// </summary>
 2545        /// <param name="snapshotsOption">
 2546        /// Specifies options for deleting blob snapshots.
 2547        /// </param>
 2548        /// <param name="conditions">
 2549        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 2550        /// deleting this blob.
 2551        /// </param>
 2552        /// <param name="async">
 2553        /// Whether to invoke the operation asynchronously.
 2554        /// </param>
 2555        /// <param name="cancellationToken">
 2556        /// Optional <see cref="CancellationToken"/> to propagate
 2557        /// notifications that the operation should be cancelled.
 2558        /// </param>
 2559        /// <returns>
 2560        /// A <see cref="Response"/> on successfully deleting.
 2561        /// </returns>
 2562        /// <remarks>
 2563        /// A <see cref="RequestFailedException"/> will be thrown if
 2564        /// a failure occurs.
 2565        /// </remarks>
 2566        private async Task<Response<bool>> DeleteIfExistsInternal(
 2567            DeleteSnapshotsOption snapshotsOption,
 2568            BlobRequestConditions conditions,
 2569            bool async,
 2570            CancellationToken cancellationToken)
 2571        {
 282572            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 2573            {
 2574                Pipeline.LogMethodEnter(
 2575                    nameof(BlobBaseClient),
 2576                    message:
 2577                    $"{nameof(Uri)}: {Uri}\n" +
 2578                    $"{nameof(snapshotsOption)}: {snapshotsOption}\n" +
 2579                    $"{nameof(conditions)}: {conditions}");
 2580                try
 2581                {
 282582                    Response response = await DeleteInternal(
 282583                        snapshotsOption,
 282584                        conditions,
 282585                        async,
 282586                        cancellationToken,
 282587                        $"{nameof(BlobBaseClient)}.{nameof(DeleteIfExists)}")
 282588                        .ConfigureAwait(false);
 82589                    return Response.FromValue(true, response);
 2590                }
 2591                catch (RequestFailedException storageRequestFailedException)
 202592                when (storageRequestFailedException.ErrorCode == BlobErrorCode.BlobNotFound
 202593                    || storageRequestFailedException.ErrorCode == BlobErrorCode.ContainerNotFound)
 2594
 2595                {
 162596                    return Response.FromValue(false, default);
 2597                }
 42598                catch (Exception ex)
 2599                {
 2600                    Pipeline.LogException(ex);
 42601                    throw;
 2602                }
 2603                finally
 2604                {
 2605                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 2606                }
 2607            }
 242608        }
 2609
 2610        /// <summary>
 2611        /// The <see cref="DeleteInternal"/> operation marks the specified blob
 2612        /// or snapshot for  deletion. The blob is later deleted during
 2613        /// garbage collection.
 2614        ///
 2615        /// Note that in order to delete a blob, you must delete all of its
 2616        /// snapshots. You can delete both at the same time using
 2617        /// <see cref="DeleteSnapshotsOption.IncludeSnapshots"/>.
 2618        ///
 2619        /// For more information, see
 2620        /// <see href="https://docs.microsoft.com/rest/api/storageservices/delete-blob">
 2621        /// Delete Blob</see>.
 2622        /// </summary>
 2623        /// <param name="snapshotsOption">
 2624        /// Specifies options for deleting blob snapshots.
 2625        /// </param>
 2626        /// <param name="conditions">
 2627        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 2628        /// deleting this blob.
 2629        /// </param>
 2630        /// <param name="async">
 2631        /// Whether to invoke the operation asynchronously.
 2632        /// </param>
 2633        /// <param name="cancellationToken">
 2634        /// Optional <see cref="CancellationToken"/> to propagate
 2635        /// notifications that the operation should be cancelled.
 2636        /// </param>
 2637        /// <param name="operationName">
 2638        /// Optional. To indicate if the name of the operation.
 2639        /// </param>
 2640        /// <returns>
 2641        /// A <see cref="Response"/> on successfully deleting.
 2642        /// </returns>
 2643        /// <remarks>
 2644        /// A <see cref="RequestFailedException"/> will be thrown if
 2645        /// a failure occurs.
 2646        /// </remarks>
 2647        private async Task<Response> DeleteInternal(
 2648            DeleteSnapshotsOption snapshotsOption,
 2649            BlobRequestConditions conditions,
 2650            bool async,
 2651            CancellationToken cancellationToken,
 2652            string operationName = null)
 2653        {
 1762654            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 2655            {
 2656                Pipeline.LogMethodEnter(
 2657                    nameof(BlobBaseClient),
 2658                    message:
 2659                    $"{nameof(Uri)}: {Uri}\n" +
 2660                    $"{nameof(snapshotsOption)}: {snapshotsOption}\n" +
 2661                    $"{nameof(conditions)}: {conditions}");
 2662                try
 2663                {
 1762664                    return await BlobRestClient.Blob.DeleteAsync(
 1762665                        ClientDiagnostics,
 1762666                        Pipeline,
 1762667                        Uri,
 1762668                        version: Version.ToVersionString(),
 1762669                        deleteSnapshots: snapshotsOption == DeleteSnapshotsOption.None ? null : (DeleteSnapshotsOption?)
 1762670                        leaseId: conditions?.LeaseId,
 1762671                        ifModifiedSince: conditions?.IfModifiedSince,
 1762672                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 1762673                        ifMatch: conditions?.IfMatch,
 1762674                        ifNoneMatch: conditions?.IfNoneMatch,
 1762675                        ifTags: conditions?.TagConditions,
 1762676                        async: async,
 1762677                        operationName: operationName ?? $"{nameof(BlobBaseClient)}.{nameof(Delete)}",
 1762678                        cancellationToken: cancellationToken)
 1762679                        .ConfigureAwait(false);
 2680                }
 562681                catch (Exception ex)
 2682                {
 2683                    Pipeline.LogException(ex);
 562684                    throw;
 2685                }
 2686                finally
 2687                {
 2688                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 2689                }
 2690            }
 1202691        }
 2692        #endregion Delete
 2693
 2694        #region Exists
 2695        /// <summary>
 2696        /// The <see cref="Exists"/> operation can be called on a
 2697        /// <see cref="BlobBaseClient"/> to see if the associated blob
 2698        /// exists in the container on the storage account in the
 2699        /// storage service.
 2700        /// </summary>
 2701        /// <param name="cancellationToken">
 2702        /// Optional <see cref="CancellationToken"/> to propagate
 2703        /// notifications that the operation should be cancelled.
 2704        /// </param>
 2705        /// <returns>
 2706        /// Returns true if the blob exists.
 2707        /// </returns>
 2708        /// <remarks>
 2709        /// A <see cref="RequestFailedException"/> will be thrown if
 2710        /// a failure occurs.
 2711        /// </remarks>
 2712        public virtual Response<bool> Exists(
 2713            CancellationToken cancellationToken = default) =>
 562714            ExistsInternal(
 562715                async: false,
 562716                cancellationToken).EnsureCompleted();
 2717
 2718        /// <summary>
 2719        /// The <see cref="ExistsAsync"/> operation can be called on a
 2720        /// <see cref="BlobBaseClient"/> to see if the associated blob
 2721        /// exists in the container on the storage account in the storage service.
 2722        /// </summary>
 2723        /// <param name="cancellationToken">
 2724        /// Optional <see cref="CancellationToken"/> to propagate
 2725        /// notifications that the operation should be cancelled.
 2726        /// </param>
 2727        /// <returns>
 2728        /// Returns true if the blob exists.
 2729        /// </returns>
 2730        /// <remarks>
 2731        /// A <see cref="RequestFailedException"/> will be thrown if
 2732        /// a failure occurs.
 2733        /// </remarks>
 2734        public virtual async Task<Response<bool>> ExistsAsync(
 2735            CancellationToken cancellationToken = default) =>
 562736            await ExistsInternal(
 562737                async: true,
 562738                cancellationToken).ConfigureAwait(false);
 2739
 2740        /// <summary>
 2741        /// The <see cref="ExistsInternal"/> operation can be called on a
 2742        /// <see cref="BlobBaseClient"/> to see if the associated blob
 2743        /// exists on the storage account in the storage service.
 2744        /// </summary>
 2745        /// <param name="async">
 2746        /// Whether to invoke the operation asynchronously.
 2747        /// </param>
 2748        /// <param name="cancellationToken">
 2749        /// Optional <see cref="CancellationToken"/> to propagate
 2750        /// notifications that the operation should be cancelled.
 2751        /// </param>
 2752        /// <returns>
 2753        /// Returns true if the blob exists.
 2754        /// </returns>
 2755        /// <remarks>
 2756        /// A <see cref="RequestFailedException"/> will be thrown if
 2757        /// a failure occurs.
 2758        /// </remarks>
 2759        private async Task<Response<bool>> ExistsInternal(
 2760            bool async,
 2761            CancellationToken cancellationToken)
 2762        {
 1122763            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 2764            {
 2765                Pipeline.LogMethodEnter(
 2766                    nameof(BlobBaseClient),
 2767                    message:
 2768                    $"{nameof(Uri)}: {Uri}");
 2769
 2770                try
 2771                {
 1122772                    Response<BlobPropertiesInternal> response = await BlobRestClient.Blob.GetPropertiesAsync(
 1122773                        ClientDiagnostics,
 1122774                        Pipeline,
 1122775                        Uri,
 1122776                        version: Version.ToVersionString(),
 1122777                        async: async,
 1122778                        operationName: $"{nameof(BlobBaseClient)}.{nameof(Exists)}",
 1122779                        cancellationToken: cancellationToken)
 1122780                        .ConfigureAwait(false);
 2781
 722782                    return Response.FromValue(true, response.GetRawResponse());
 2783                }
 2784                catch (RequestFailedException storageRequestFailedException)
 402785                when (storageRequestFailedException.ErrorCode == BlobErrorCode.BlobNotFound
 402786                    || storageRequestFailedException.ErrorCode == BlobErrorCode.ContainerNotFound)
 2787                {
 282788                    return Response.FromValue(false, default);
 2789                }
 122790                catch (Exception ex)
 2791                {
 2792                    Pipeline.LogException(ex);
 122793                    throw;
 2794                }
 2795                finally
 2796                {
 2797                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 2798                }
 2799            }
 1002800        }
 2801        #endregion Exists
 2802
 2803        #region Undelete
 2804        /// <summary>
 2805        /// The <see cref="Undelete"/> operation restores the contents
 2806        /// and metadata of a soft deleted blob and any associated soft
 2807        /// deleted snapshots.
 2808        ///
 2809        /// For more information, see
 2810        /// <see href="https://docs.microsoft.com/rest/api/storageservices/undelete-blob">
 2811        /// Undelete Blob</see>.
 2812        /// </summary>
 2813        /// <param name="cancellationToken">
 2814        /// Optional <see cref="CancellationToken"/> to propagate
 2815        /// notifications that the operation should be cancelled.
 2816        /// </param>
 2817        /// <returns>
 2818        /// A <see cref="Response"/> on successfully deleting.
 2819        /// </returns>
 2820        /// <remarks>
 2821        /// A <see cref="RequestFailedException"/> will be thrown if
 2822        /// a failure occurs.
 2823        /// </remarks>
 2824        public virtual Response Undelete(
 2825            CancellationToken cancellationToken = default) =>
 42826            UndeleteInternal(
 42827                false, // async
 42828                cancellationToken)
 42829                .EnsureCompleted();
 2830
 2831        /// <summary>
 2832        /// The <see cref="UndeleteAsync"/> operation restores the contents
 2833        /// and metadata of a soft deleted blob and any associated soft
 2834        /// deleted snapshots.
 2835        ///
 2836        /// For more information, see
 2837        /// <see href="https://docs.microsoft.com/rest/api/storageservices/undelete-blob">
 2838        /// Undelete Blob</see>.
 2839        /// </summary>
 2840        /// <param name="cancellationToken">
 2841        /// Optional <see cref="CancellationToken"/> to propagate
 2842        /// notifications that the operation should be cancelled.
 2843        /// </param>
 2844        /// <returns>
 2845        /// A <see cref="Response"/> on successfully deleting.
 2846        /// </returns>
 2847        /// <remarks>
 2848        /// A <see cref="RequestFailedException"/> will be thrown if
 2849        /// a failure occurs.
 2850        /// </remarks>
 2851        public virtual async Task<Response> UndeleteAsync(
 2852            CancellationToken cancellationToken = default) =>
 42853            await UndeleteInternal(
 42854                true, // async
 42855                cancellationToken)
 42856                .ConfigureAwait(false);
 2857
 2858        /// <summary>
 2859        /// The <see cref="UndeleteInternal"/> operation restores the contents
 2860        /// and metadata of a soft deleted blob and any associated soft
 2861        /// deleted snapshots.
 2862        ///
 2863        /// For more information, see
 2864        /// <see href="https://docs.microsoft.com/rest/api/storageservices/undelete-blob">
 2865        /// Undelete Blob</see>.
 2866        /// </summary>
 2867        /// <param name="async">
 2868        /// Whether to invoke the operation asynchronously.
 2869        /// </param>
 2870        /// <param name="cancellationToken">
 2871        /// Optional <see cref="CancellationToken"/> to propagate
 2872        /// notifications that the operation should be cancelled.
 2873        /// </param>
 2874        /// <returns>
 2875        /// A <see cref="Response"/> on successfully deleting.
 2876        /// </returns>
 2877        /// <remarks>
 2878        /// A <see cref="RequestFailedException"/> will be thrown if
 2879        /// a failure occurs.
 2880        /// </remarks>
 2881        private async Task<Response> UndeleteInternal(
 2882            bool async,
 2883            CancellationToken cancellationToken)
 2884        {
 82885            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 2886            {
 2887                Pipeline.LogMethodEnter(nameof(BlobBaseClient), message: $"{nameof(Uri)}: {Uri}");
 2888                try
 2889                {
 82890                    return await BlobRestClient.Blob.UndeleteAsync(
 82891                        ClientDiagnostics,
 82892                        Pipeline,
 82893                        Uri,
 82894                        version: Version.ToVersionString(),
 82895                        async: async,
 82896                        cancellationToken: cancellationToken,
 82897                        operationName: "BlobBaseClient.Undelete")
 82898                        .ConfigureAwait(false);
 2899                }
 42900                catch (Exception ex)
 2901                {
 2902                    Pipeline.LogException(ex);
 42903                    throw;
 2904                }
 2905                finally
 2906                {
 2907                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 2908                }
 2909            }
 42910        }
 2911        #endregion Undelete
 2912
 2913        #region GetProperties
 2914        /// <summary>
 2915        /// The <see cref="GetProperties"/> operation returns all
 2916        /// user-defined metadata, standard HTTP properties, and system
 2917        /// properties for the blob. It does not return the content of the
 2918        /// blob.
 2919        ///
 2920        /// For more information, see
 2921        /// <see href="https://docs.microsoft.com/rest/api/storageservices/get-blob-properties">
 2922        /// Get Blob Properties</see>.
 2923        /// </summary>
 2924        /// <param name="conditions">
 2925        /// Optional <see cref="BlobRequestConditions"/> to add
 2926        /// conditions on getting the blob's properties.
 2927        /// </param>
 2928        /// <param name="cancellationToken">
 2929        /// Optional <see cref="CancellationToken"/> to propagate
 2930        /// notifications that the operation should be cancelled.
 2931        /// </param>
 2932        /// <returns>
 2933        /// A <see cref="Response{BlobProperties}"/> describing the
 2934        /// blob's properties.
 2935        /// </returns>
 2936        /// <remarks>
 2937        /// A <see cref="RequestFailedException"/> will be thrown if
 2938        /// a failure occurs.
 2939        /// </remarks>
 2940        public virtual Response<BlobProperties> GetProperties(
 2941            BlobRequestConditions conditions = default,
 2942            CancellationToken cancellationToken = default) =>
 4542943            GetPropertiesInternal(
 4542944                conditions,
 4542945                false, // async
 4542946                cancellationToken)
 4542947                .EnsureCompleted();
 2948
 2949        /// <summary>
 2950        /// The <see cref="GetPropertiesAsync"/> operation returns all
 2951        /// user-defined metadata, standard HTTP properties, and system
 2952        /// properties for the blob. It does not return the content of the
 2953        /// blob.
 2954        ///
 2955        /// For more information, see
 2956        /// <see href="https://docs.microsoft.com/rest/api/storageservices/get-blob-properties">
 2957        /// Get Blob Properties</see>.
 2958        /// </summary>
 2959        /// <param name="conditions">
 2960        /// Optional <see cref="BlobRequestConditions"/> to add
 2961        /// conditions on getting the blob's properties.
 2962        /// </param>
 2963        /// <param name="cancellationToken">
 2964        /// Optional <see cref="CancellationToken"/> to propagate
 2965        /// notifications that the operation should be cancelled.
 2966        /// </param>
 2967        /// <returns>
 2968        /// A <see cref="Response{BlobProperties}"/> describing the
 2969        /// blob's properties.
 2970        /// </returns>
 2971        /// <remarks>
 2972        /// A <see cref="RequestFailedException"/> will be thrown if
 2973        /// a failure occurs.
 2974        /// </remarks>
 2975        public virtual async Task<Response<BlobProperties>> GetPropertiesAsync(
 2976            BlobRequestConditions conditions = default,
 2977            CancellationToken cancellationToken = default) =>
 11022978            await GetPropertiesInternal(
 11022979                conditions,
 11022980                true, // async
 11022981                cancellationToken)
 11022982                .ConfigureAwait(false);
 2983
 2984        /// <summary>
 2985        /// The <see cref="GetPropertiesInternal"/> operation returns all
 2986        /// user-defined metadata, standard HTTP properties, and system
 2987        /// properties for the blob. It does not return the content of the
 2988        /// blob.
 2989        ///
 2990        /// For more information, see
 2991        /// <see href="https://docs.microsoft.com/rest/api/storageservices/get-blob-properties">
 2992        /// Get Blob Properties</see>.
 2993        /// </summary>
 2994        /// <param name="conditions">
 2995        /// Optional <see cref="BlobRequestConditions"/> to add
 2996        /// conditions on getting the blob's properties.
 2997        /// </param>
 2998        /// <param name="async">
 2999        /// Whether to invoke the operation asynchronously.
 3000        /// </param>
 3001        /// <param name="cancellationToken">
 3002        /// Optional <see cref="CancellationToken"/> to propagate
 3003        /// notifications that the operation should be cancelled.
 3004        /// </param>
 3005        /// <returns>
 3006        /// A <see cref="Response{BlobProperties}"/> describing the
 3007        /// blob's properties.
 3008        /// </returns>
 3009        /// <remarks>
 3010        /// A <see cref="RequestFailedException"/> will be thrown if
 3011        /// a failure occurs.
 3012        /// </remarks>
 3013        private async Task<Response<BlobProperties>> GetPropertiesInternal(
 3014            BlobRequestConditions conditions,
 3015            bool async,
 3016            CancellationToken cancellationToken)
 3017        {
 15643018            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 3019            {
 3020                Pipeline.LogMethodEnter(
 3021                    nameof(BlobBaseClient),
 3022                    message:
 3023                    $"{nameof(Uri)}: {Uri}\n" +
 3024                    $"{nameof(conditions)}: {conditions}");
 3025                try
 3026                {
 15643027                    Response<BlobPropertiesInternal> response = await BlobRestClient.Blob.GetPropertiesAsync(
 15643028                        ClientDiagnostics,
 15643029                        Pipeline,
 15643030                        Uri,
 15643031                        version: Version.ToVersionString(),
 15643032                        leaseId: conditions?.LeaseId,
 15643033                        encryptionKey: CustomerProvidedKey?.EncryptionKey,
 15643034                        encryptionKeySha256: CustomerProvidedKey?.EncryptionKeyHash,
 15643035                        encryptionAlgorithm: CustomerProvidedKey?.EncryptionAlgorithm,
 15643036                        ifModifiedSince: conditions?.IfModifiedSince,
 15643037                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 15643038                        ifMatch: conditions?.IfMatch,
 15643039                        ifNoneMatch: conditions?.IfNoneMatch,
 15643040                        ifTags: conditions?.TagConditions,
 15643041                        async: async,
 15643042                        operationName: "BlobBaseClient.GetProperties",
 15643043                        cancellationToken: cancellationToken)
 15643044                        .ConfigureAwait(false);
 3045
 13963046                    return Response.FromValue(
 13963047                        response.Value.ToBlobProperties(),
 13963048                        response.GetRawResponse());
 3049                }
 1923050                catch (Exception ex)
 3051                {
 3052                    Pipeline.LogException(ex);
 1923053                    throw;
 3054                }
 3055                finally
 3056                {
 3057                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 3058                }
 3059            }
 13723060        }
 3061        #endregion GetProperties
 3062
 3063        #region SetHttpHeaders
 3064        /// <summary>
 3065        /// The <see cref="SetHttpHeaders"/> operation sets system
 3066        /// properties on the blob.
 3067        ///
 3068        /// For more information, see
 3069        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-properties">
 3070        /// Set Blob Properties</see>.
 3071        /// </summary>
 3072        /// <param name="httpHeaders">
 3073        /// Optional. The standard HTTP header system properties to set.
 3074        /// If not specified, existing values will be cleared.
 3075        /// </param>
 3076        /// <param name="conditions">
 3077        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3078        /// setting the blob's HTTP headers.
 3079        /// </param>
 3080        /// <param name="cancellationToken">
 3081        /// Optional <see cref="CancellationToken"/> to propagate
 3082        /// notifications that the operation should be cancelled.
 3083        /// </param>
 3084        /// <returns>
 3085        /// A <see cref="Response{BlobInfo}"/> describing the updated
 3086        /// blob.
 3087        /// </returns>
 3088        /// <remarks>
 3089        /// A <see cref="RequestFailedException"/> will be thrown if
 3090        /// a failure occurs.
 3091        /// </remarks>
 3092        public virtual Response<BlobInfo> SetHttpHeaders(
 3093            BlobHttpHeaders httpHeaders = default,
 3094            BlobRequestConditions conditions = default,
 3095            CancellationToken cancellationToken = default) =>
 363096            SetHttpHeadersInternal(
 363097                httpHeaders,
 363098                conditions,
 363099                false, // async
 363100                cancellationToken)
 363101                .EnsureCompleted();
 3102
 3103        /// <summary>
 3104        /// The <see cref="SetHttpHeadersAsync"/> operation sets system
 3105        /// properties on the blob.
 3106        ///
 3107        /// For more information, see
 3108        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-properties">
 3109        /// Set Blob Properties</see>.
 3110        /// </summary>
 3111        /// <param name="httpHeaders">
 3112        /// Optional. The standard HTTP header system properties to set.  If not specified, existing values will be clea
 3113        /// </param>
 3114        /// <param name="conditions">
 3115        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3116        /// setting the blob's HTTP headers.
 3117        /// </param>
 3118        /// <param name="cancellationToken">
 3119        /// Optional <see cref="CancellationToken"/> to propagate
 3120        /// notifications that the operation should be cancelled.
 3121        /// </param>
 3122        /// <returns>
 3123        /// A <see cref="Response{BlobInfo}"/> describing the updated
 3124        /// blob.
 3125        /// </returns>
 3126        /// <remarks>
 3127        /// A <see cref="RequestFailedException"/> will be thrown if
 3128        /// a failure occurs.
 3129        /// </remarks>
 3130        public virtual async Task<Response<BlobInfo>> SetHttpHeadersAsync(
 3131            BlobHttpHeaders httpHeaders = default,
 3132            BlobRequestConditions conditions = default,
 3133            CancellationToken cancellationToken = default) =>
 1323134            await SetHttpHeadersInternal(
 1323135                httpHeaders,
 1323136                conditions,
 1323137                true, // async
 1323138                cancellationToken)
 1323139                .ConfigureAwait(false);
 3140
 3141        /// <summary>
 3142        /// The <see cref="SetHttpHeadersInternal"/> operation sets system
 3143        /// properties on the blob.
 3144        ///
 3145        /// For more information, see
 3146        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-properties">
 3147        /// Set Blob Properties</see>.
 3148        /// </summary>
 3149        /// <param name="httpHeaders">
 3150        /// Optional. The standard HTTP header system properties to set.  If not specified, existing values will be clea
 3151        /// </param>
 3152        /// <param name="conditions">
 3153        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3154        /// setting the blob's HTTP headers.
 3155        /// </param>
 3156        /// <param name="async">
 3157        /// Whether to invoke the operation asynchronously.
 3158        /// </param>
 3159        /// <param name="cancellationToken">
 3160        /// Optional <see cref="CancellationToken"/> to propagate
 3161        /// notifications that the operation should be cancelled.
 3162        /// </param>
 3163        /// <returns>
 3164        /// A <see cref="Response{BlobInfo}"/> describing the updated
 3165        /// blob.
 3166        /// </returns>
 3167        /// <remarks>
 3168        /// A <see cref="RequestFailedException"/> will be thrown if
 3169        /// a failure occurs.
 3170        /// </remarks>
 3171        private async Task<Response<BlobInfo>> SetHttpHeadersInternal(
 3172            BlobHttpHeaders httpHeaders,
 3173            BlobRequestConditions conditions,
 3174            bool async,
 3175            CancellationToken cancellationToken)
 3176        {
 1683177            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 3178            {
 3179                Pipeline.LogMethodEnter(
 3180                    nameof(BlobBaseClient),
 3181                    message:
 3182                    $"{nameof(Uri)}: {Uri}\n" +
 3183                    $"{nameof(httpHeaders)}: {httpHeaders}\n" +
 3184                    $"{nameof(conditions)}: {conditions}");
 3185                try
 3186                {
 1683187                    Response<SetHttpHeadersOperation> response =
 1683188                        await BlobRestClient.Blob.SetHttpHeadersAsync(
 1683189                            ClientDiagnostics,
 1683190                            Pipeline,
 1683191                            Uri,
 1683192                            version: Version.ToVersionString(),
 1683193                            blobCacheControl: httpHeaders?.CacheControl,
 1683194                            blobContentType: httpHeaders?.ContentType,
 1683195                            blobContentHash: httpHeaders?.ContentHash,
 1683196                            blobContentEncoding: httpHeaders?.ContentEncoding,
 1683197                            blobContentLanguage: httpHeaders?.ContentLanguage,
 1683198                            blobContentDisposition: httpHeaders?.ContentDisposition,
 1683199                            leaseId: conditions?.LeaseId,
 1683200                            ifModifiedSince: conditions?.IfModifiedSince,
 1683201                            ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 1683202                            ifMatch: conditions?.IfMatch,
 1683203                            ifNoneMatch: conditions?.IfNoneMatch,
 1683204                            ifTags: conditions?.TagConditions,
 1683205                            async: async,
 1683206                            operationName: "BlobBaseClient.SetHttpHeaders",
 1683207                            cancellationToken: cancellationToken)
 1683208                            .ConfigureAwait(false);
 923209                    return Response.FromValue(
 923210                        new BlobInfo
 923211                        {
 923212                            LastModified = response.Value.LastModified,
 923213                            ETag = response.Value.ETag,
 923214                            BlobSequenceNumber = response.Value.BlobSequenceNumber
 923215                        }, response.GetRawResponse());
 3216                }
 763217                catch (Exception ex)
 3218                {
 3219                    Pipeline.LogException(ex);
 763220                    throw;
 3221                }
 3222                finally
 3223                {
 3224                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 3225                }
 3226            }
 923227        }
 3228        #endregion SetHttpHeaders
 3229
 3230        #region SetMetadata
 3231        /// <summary>
 3232        /// The <see cref="SetMetadata"/> operation sets user-defined
 3233        /// metadata for the specified blob as one or more name-value pairs.
 3234        ///
 3235        /// For more information, see
 3236        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-metadata">
 3237        /// Set Blob Metadata</see>.
 3238        /// </summary>
 3239        /// <param name="metadata">
 3240        /// Custom metadata to set for this blob.
 3241        /// </param>
 3242        /// <param name="conditions">
 3243        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3244        /// setting the blob's metadata.
 3245        /// </param>
 3246        /// <param name="cancellationToken">
 3247        /// Optional <see cref="CancellationToken"/> to propagate
 3248        /// notifications that the operation should be cancelled.
 3249        /// </param>
 3250        /// <returns>
 3251        /// A <see cref="Response{BlobInfo}"/> describing the updated
 3252        /// blob.
 3253        /// </returns>
 3254        /// <remarks>
 3255        /// A <see cref="RequestFailedException"/> will be thrown if
 3256        /// a failure occurs.
 3257        /// </remarks>
 3258        public virtual Response<BlobInfo> SetMetadata(
 3259            Metadata metadata,
 3260            BlobRequestConditions conditions = default,
 3261            CancellationToken cancellationToken = default) =>
 883262            SetMetadataInternal(
 883263                metadata,
 883264                conditions,
 883265                false, // async
 883266                cancellationToken)
 883267                .EnsureCompleted();
 3268
 3269        /// <summary>
 3270        /// The <see cref="SetMetadataAsync"/> operation sets user-defined
 3271        /// metadata for the specified blob as one or more name-value pairs.
 3272        ///
 3273        /// For more information, see
 3274        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-metadata">
 3275        /// Set Blob Metadata</see>.
 3276        /// </summary>
 3277        /// <param name="metadata">
 3278        /// Custom metadata to set for this blob.
 3279        /// </param>
 3280        /// <param name="conditions">
 3281        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3282        /// setting the blob's metadata.
 3283        /// </param>
 3284        /// <param name="cancellationToken">
 3285        /// Optional <see cref="CancellationToken"/> to propagate
 3286        /// notifications that the operation should be cancelled.
 3287        /// </param>
 3288        /// <returns>
 3289        /// A <see cref="Response{BlobInfo}"/> describing the updated
 3290        /// blob.
 3291        /// </returns>
 3292        /// <remarks>
 3293        /// A <see cref="RequestFailedException"/> will be thrown if
 3294        /// a failure occurs.
 3295        /// </remarks>
 3296        public virtual async Task<Response<BlobInfo>> SetMetadataAsync(
 3297            Metadata metadata,
 3298            BlobRequestConditions conditions = default,
 3299            CancellationToken cancellationToken = default) =>
 1883300            await SetMetadataInternal(
 1883301                metadata,
 1883302                conditions,
 1883303                true, // async
 1883304                cancellationToken)
 1883305                .ConfigureAwait(false);
 3306
 3307        /// <summary>
 3308        /// The <see cref="SetMetadataInternal"/> operation sets user-defined
 3309        /// metadata for the specified blob as one or more name-value pairs.
 3310        ///
 3311        /// For more information, see
 3312        /// <see href="https://docs.microsoft.com/rest/api/storageservices/set-blob-metadata">
 3313        /// Set Blob Metadata</see>.
 3314        /// </summary>
 3315        /// <param name="metadata">
 3316        /// Custom metadata to set for this blob.
 3317        /// </param>
 3318        /// <param name="conditions">
 3319        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3320        /// setting the blob's metadata.
 3321        /// </param>
 3322        /// <param name="async">
 3323        /// Whether to invoke the operation asynchronously.
 3324        /// </param>
 3325        /// <param name="cancellationToken">
 3326        /// Optional <see cref="CancellationToken"/> to propagate
 3327        /// notifications that the operation should be cancelled.
 3328        /// </param>
 3329        /// <returns>
 3330        /// A <see cref="Response{BlobInfo}"/> describing the updated
 3331        /// blob.
 3332        /// </returns>
 3333        /// <remarks>
 3334        /// A <see cref="RequestFailedException"/> will be thrown if
 3335        /// a failure occurs.
 3336        /// </remarks>
 3337        private async Task<Response<BlobInfo>> SetMetadataInternal(
 3338            Metadata metadata,
 3339            BlobRequestConditions conditions,
 3340            bool async,
 3341            CancellationToken cancellationToken)
 3342        {
 2763343            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 3344            {
 3345                Pipeline.LogMethodEnter(
 3346                    nameof(BlobBaseClient),
 3347                    message:
 3348                    $"{nameof(Uri)}: {Uri}\n" +
 3349                    $"{nameof(conditions)}: {conditions}");
 3350                try
 3351                {
 2763352                    Response<SetMetadataOperation> response =
 2763353                        await BlobRestClient.Blob.SetMetadataAsync(
 2763354                            ClientDiagnostics,
 2763355                            Pipeline,
 2763356                            Uri,
 2763357                            version: Version.ToVersionString(),
 2763358                            metadata: metadata,
 2763359                            leaseId: conditions?.LeaseId,
 2763360                            encryptionKey: CustomerProvidedKey?.EncryptionKey,
 2763361                            encryptionKeySha256: CustomerProvidedKey?.EncryptionKeyHash,
 2763362                            encryptionAlgorithm: CustomerProvidedKey?.EncryptionAlgorithm,
 2763363                            encryptionScope: EncryptionScope,
 2763364                            ifModifiedSince: conditions?.IfModifiedSince,
 2763365                            ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 2763366                            ifMatch: conditions?.IfMatch,
 2763367                            ifNoneMatch: conditions?.IfNoneMatch,
 2763368                            ifTags: conditions?.TagConditions,
 2763369                            async: async,
 2763370                            operationName: "BlobBaseClient.SetMetadata",
 2763371                            cancellationToken: cancellationToken)
 2763372                            .ConfigureAwait(false);
 2003373                    return Response.FromValue(
 2003374                        new BlobInfo
 2003375                        {
 2003376                            LastModified = response.Value.LastModified,
 2003377                            ETag = response.Value.ETag,
 2003378                            VersionId = response.Value.VersionId
 2003379                        }, response.GetRawResponse());
 3380                }
 763381                catch (Exception ex)
 3382                {
 3383                    Pipeline.LogException(ex);
 763384                    throw;
 3385                }
 3386                finally
 3387                {
 3388                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 3389                }
 3390            }
 2003391        }
 3392        #endregion SetMetadata
 3393
 3394        #region CreateSnapshot
 3395        /// <summary>
 3396        /// The <see cref="CreateSnapshot"/> operation creates a
 3397        /// read-only snapshot of a blob.
 3398        ///
 3399        /// For more information, see
 3400        /// <see href="https://docs.microsoft.com/rest/api/storageservices/snapshot-blob">
 3401        /// Snapshot Blob</see>.
 3402        /// </summary>
 3403        /// <param name="metadata">
 3404        /// Optional custom metadata to set for this blob snapshot.
 3405        /// </param>
 3406        /// <param name="conditions">
 3407        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3408        /// setting creating this snapshot.
 3409        /// </param>
 3410        /// <param name="cancellationToken">
 3411        /// Optional <see cref="CancellationToken"/> to propagate
 3412        /// notifications that the operation should be cancelled.
 3413        /// </param>
 3414        /// <returns>
 3415        /// A <see cref="Response{BlobSnapshotInfo}"/> describing the
 3416        /// new blob snapshot.
 3417        /// </returns>
 3418        /// <remarks>
 3419        /// A <see cref="RequestFailedException"/> will be thrown if
 3420        /// a failure occurs.
 3421        /// </remarks>
 3422        public virtual Response<BlobSnapshotInfo> CreateSnapshot(
 3423            Metadata metadata = default,
 3424            BlobRequestConditions conditions = default,
 3425            CancellationToken cancellationToken = default) =>
 1763426            CreateSnapshotInternal(
 1763427                metadata,
 1763428                conditions,
 1763429                false, // async
 1763430                cancellationToken)
 1763431                .EnsureCompleted();
 3432
 3433        /// <summary>
 3434        /// The <see cref="CreateSnapshotAsync"/> operation creates a
 3435        /// read-only snapshot of a blob.
 3436        ///
 3437        /// For more information, see
 3438        /// <see href="https://docs.microsoft.com/rest/api/storageservices/snapshot-blob">
 3439        /// Snapshot Blob</see>.
 3440        /// </summary>
 3441        /// <param name="metadata">
 3442        /// Optional custom metadata to set for this blob snapshot.
 3443        /// </param>
 3444        /// <param name="conditions">
 3445        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3446        /// setting creating this snapshot.
 3447        /// </param>
 3448        /// <param name="cancellationToken">
 3449        /// Optional <see cref="CancellationToken"/> to propagate
 3450        /// notifications that the operation should be cancelled.
 3451        /// </param>
 3452        /// <returns>
 3453        /// A <see cref="Response{BlobSnapshotInfo}"/> describing the
 3454        /// new blob snapshot.
 3455        /// </returns>
 3456        /// <remarks>
 3457        /// A <see cref="RequestFailedException"/> will be thrown if
 3458        /// a failure occurs.
 3459        /// </remarks>
 3460        public virtual async Task<Response<BlobSnapshotInfo>> CreateSnapshotAsync(
 3461            Metadata metadata = default,
 3462            BlobRequestConditions conditions = default,
 3463            CancellationToken cancellationToken = default) =>
 1763464            await CreateSnapshotInternal(
 1763465                metadata,
 1763466                conditions,
 1763467                true, // async
 1763468                cancellationToken)
 1763469                .ConfigureAwait(false);
 3470
 3471        /// <summary>
 3472        /// The <see cref="CreateSnapshotInternal"/> operation creates a
 3473        /// read-only snapshot of a blob.
 3474        ///
 3475        /// For more information, see
 3476        /// <see href="https://docs.microsoft.com/rest/api/storageservices/snapshot-blob">
 3477        /// Snapshot Blob</see>.
 3478        /// </summary>
 3479        /// <param name="metadata">
 3480        /// Optional custom metadata to set for this blob snapshot.
 3481        /// </param>
 3482        /// <param name="conditions">
 3483        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3484        /// setting creating this snapshot.
 3485        /// </param>
 3486        /// <param name="async">
 3487        /// Whether to invoke the operation asynchronously.
 3488        /// </param>
 3489        /// <param name="cancellationToken">
 3490        /// Optional <see cref="CancellationToken"/> to propagate
 3491        /// notifications that the operation should be cancelled.
 3492        /// </param>
 3493        /// <returns>
 3494        /// A <see cref="Response{BlobSnapshotInfo}"/> describing the
 3495        /// new blob snapshot.
 3496        /// </returns>
 3497        /// <remarks>
 3498        /// A <see cref="RequestFailedException"/> will be thrown if
 3499        /// a failure occurs.
 3500        /// </remarks>
 3501        private async Task<Response<BlobSnapshotInfo>> CreateSnapshotInternal(
 3502            Metadata metadata,
 3503            BlobRequestConditions conditions,
 3504            bool async,
 3505            CancellationToken cancellationToken)
 3506        {
 3523507            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 3508            {
 3509                Pipeline.LogMethodEnter(
 3510                    nameof(BlobBaseClient),
 3511                    message:
 3512                    $"{nameof(Uri)}: {Uri}\n" +
 3513                    $"{nameof(conditions)}: {conditions}");
 3514                try
 3515                {
 3523516                    return await BlobRestClient.Blob.CreateSnapshotAsync(
 3523517                        ClientDiagnostics,
 3523518                        Pipeline,
 3523519                        Uri,
 3523520                        version: Version.ToVersionString(),
 3523521                        metadata: metadata,
 3523522                        encryptionKey: CustomerProvidedKey?.EncryptionKey,
 3523523                        encryptionKeySha256: CustomerProvidedKey?.EncryptionKeyHash,
 3523524                        encryptionAlgorithm: CustomerProvidedKey?.EncryptionAlgorithm,
 3523525                        encryptionScope: EncryptionScope,
 3523526                        ifModifiedSince: conditions?.IfModifiedSince,
 3523527                        ifUnmodifiedSince: conditions?.IfUnmodifiedSince,
 3523528                        ifMatch: conditions?.IfMatch,
 3523529                        ifNoneMatch: conditions?.IfNoneMatch,
 3523530                        leaseId: conditions?.LeaseId,
 3523531                        ifTags: conditions?.TagConditions,
 3523532                        async: async,
 3523533                        operationName: "BlobBaseClient.CreateSnapshot",
 3523534                        cancellationToken: cancellationToken)
 3523535                        .ConfigureAwait(false);
 3536                }
 283537                catch (Exception ex)
 3538                {
 3539                    Pipeline.LogException(ex);
 283540                    throw;
 3541                }
 3542                finally
 3543                {
 3544                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 3545                }
 3546            }
 3243547        }
 3548        #endregion CreateSnapshot
 3549
 3550        #region SetAccessTier
 3551        /// <summary>
 3552        /// The <see cref="SetAccessTier"/> operation sets the tier on a blob.
 3553        /// The operation is allowed on a page blob in a premium storage
 3554        /// account and on a block blob in a blob storage or general purpose
 3555        /// v2 account.
 3556        ///
 3557        /// A premium page blob's tier determines the allowed size, IOPS, and
 3558        /// bandwidth of the blob.  A block blob's tier determines
 3559        /// Hot/Cool/Archive storage type.  This operation does not update the
 3560        /// blob's ETag.  For detailed information about block blob level
 3561        /// tiering <see href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-storage-tiers">
 3562        /// Blob Storage Tiers</see>.
 3563        ///
 3564        /// For more information about setting the tier, see
 3565        /// <see href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-storage-tiers">
 3566        /// Blob Storage Tiers</see>.
 3567        /// </summary>
 3568        /// <param name="accessTier">
 3569        /// Indicates the tier to be set on the blob.
 3570        /// </param>
 3571        /// <param name="conditions">
 3572        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3573        /// setting the access tier.
 3574        /// </param>
 3575        /// <param name="rehydratePriority">
 3576        /// Optional <see cref="RehydratePriority"/>
 3577        /// Indicates the priority with which to rehydrate an archived blob.
 3578        /// </param>
 3579        /// <param name="cancellationToken">
 3580        /// Optional <see cref="CancellationToken"/> to propagate
 3581        /// notifications that the operation should be cancelled.
 3582        /// </param>
 3583        /// <returns>
 3584        /// A <see cref="Response"/> on successfully setting the tier.
 3585        /// </returns>
 3586        /// <remarks>
 3587        /// A <see cref="RequestFailedException"/> will be thrown if
 3588        /// a failure occurs.
 3589        /// </remarks>
 3590        public virtual Response SetAccessTier(
 3591            AccessTier accessTier,
 3592            BlobRequestConditions conditions = default,
 3593            RehydratePriority? rehydratePriority = default,
 3594            CancellationToken cancellationToken = default) =>
 523595            SetAccessTierInternal(
 523596                accessTier,
 523597                conditions,
 523598                rehydratePriority,
 523599                false, // async
 523600                cancellationToken)
 523601                .EnsureCompleted();
 3602
 3603        /// <summary>
 3604        /// The <see cref="SetAccessTierAsync"/> operation sets the tier on a blob.
 3605        /// The operation is allowed on a page blob in a premium storage
 3606        /// account and on a block blob in a blob storage or general purpose
 3607        /// v2 account.
 3608        ///
 3609        /// A premium page blob's tier determines the allowed size, IOPS, and
 3610        /// bandwidth of the blob.  A block blob's tier determines
 3611        /// Hot/Cool/Archive storage type.  This operation does not update the
 3612        /// blob's ETag.  For detailed information about block blob level
 3613        /// tiering <see href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-storage-tiers">
 3614        /// Blob Storage Tiers</see>.
 3615        ///
 3616        /// For more information about setting the tier, see
 3617        /// <see href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-storage-tiers">
 3618        /// Blob Storage Tiers</see>.
 3619        /// </summary>
 3620        /// <param name="accessTier">
 3621        /// Indicates the tier to be set on the blob.
 3622        /// </param>
 3623        /// <param name="conditions">
 3624        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3625        /// setting the access tier.
 3626        /// </param>
 3627        /// <param name="rehydratePriority">
 3628        /// Optional <see cref="RehydratePriority"/>
 3629        /// Indicates the priority with which to rehydrate an archived blob.
 3630        /// </param>
 3631        /// <param name="cancellationToken">
 3632        /// Optional <see cref="CancellationToken"/> to propagate
 3633        /// notifications that the operation should be cancelled.
 3634        /// </param>
 3635        /// <returns>
 3636        /// A <see cref="Response"/> on successfully setting the tier.
 3637        /// </returns>
 3638        /// <remarks>
 3639        /// A <see cref="RequestFailedException"/> will be thrown if
 3640        /// a failure occurs.
 3641        /// </remarks>
 3642        public virtual async Task<Response> SetAccessTierAsync(
 3643            AccessTier accessTier,
 3644            BlobRequestConditions conditions = default,
 3645            RehydratePriority? rehydratePriority = default,
 3646            CancellationToken cancellationToken = default) =>
 563647            await SetAccessTierInternal(
 563648                accessTier,
 563649                conditions,
 563650                rehydratePriority,
 563651                true, // async
 563652                cancellationToken)
 563653                .ConfigureAwait(false);
 3654
 3655        /// <summary>
 3656        /// The <see cref="SetAccessTierInternal"/> operation sets the tier on a blob.
 3657        /// The operation is allowed on a page blob in a premium storage
 3658        /// account and on a block blob in a blob storage or general purpose
 3659        /// v2 account.
 3660        ///
 3661        /// A premium page blob's tier determines the allowed size, IOPS, and
 3662        /// bandwidth of the blob.  A block blob's tier determines
 3663        /// Hot/Cool/Archive storage type.  This operation does not update the
 3664        /// blob's ETag.  For detailed information about block blob level
 3665        /// tiering <see href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-storage-tiers">
 3666        /// Blob Storage Tiers</see>.
 3667        ///
 3668        /// For more information about setting the tier, see
 3669        /// <see href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-storage-tiers">
 3670        /// Blob Storage Tiers</see>.
 3671        /// </summary>
 3672        /// <param name="accessTier">
 3673        /// Indicates the tier to be set on the blob.
 3674        /// </param>
 3675        /// <param name="conditions">
 3676        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3677        /// setting the access tier.
 3678        /// </param>
 3679        /// <param name="rehydratePriority">
 3680        /// Optional <see cref="RehydratePriority"/>
 3681        /// Indicates the priority with which to rehydrate an archived blob.
 3682        /// </param>
 3683        /// <param name="async">
 3684        /// Whether to invoke the operation asynchronously.
 3685        /// </param>
 3686        /// <param name="cancellationToken">
 3687        /// Optional <see cref="CancellationToken"/> to propagate
 3688        /// notifications that the operation should be cancelled.
 3689        /// </param>
 3690        /// <returns>
 3691        /// A <see cref="Response"/> on successfully setting the tier.
 3692        /// </returns>
 3693        /// <remarks>
 3694        /// A <see cref="RequestFailedException"/> will be thrown if
 3695        /// a failure occurs.
 3696        /// </remarks>
 3697        private async Task<Response> SetAccessTierInternal(
 3698            AccessTier accessTier,
 3699            BlobRequestConditions conditions,
 3700            RehydratePriority? rehydratePriority,
 3701            bool async,
 3702            CancellationToken cancellationToken)
 3703        {
 1083704            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 3705            {
 3706                Pipeline.LogMethodEnter(
 3707                    nameof(BlobBaseClient),
 3708                    message:
 3709                    $"{nameof(Uri)}: {Uri}\n" +
 3710                    $"{nameof(accessTier)}: {accessTier}\n" +
 3711                    $"{nameof(conditions)}: {conditions}");
 3712                try
 3713                {
 1083714                    return await BlobRestClient.Blob.SetAccessTierAsync(
 1083715                        ClientDiagnostics,
 1083716                        Pipeline,
 1083717                        Uri,
 1083718                        tier: accessTier,
 1083719                        version: Version.ToVersionString(),
 1083720                        rehydratePriority: rehydratePriority,
 1083721                        leaseId: conditions?.LeaseId,
 1083722                        ifTags: conditions?.TagConditions,
 1083723                        async: async,
 1083724                        operationName: "BlobBaseClient.SetAccessTier",
 1083725                        cancellationToken: cancellationToken)
 1083726                        .ConfigureAwait(false);
 3727                }
 243728                catch (Exception ex)
 3729                {
 3730                    Pipeline.LogException(ex);
 243731                    throw;
 3732                }
 3733                finally
 3734                {
 3735                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 3736                }
 3737            }
 843738        }
 3739        #endregion SetAccessTier
 3740
 3741        #region GetTags
 3742        /// <summary>
 3743        /// Gets the tags associated with the underlying blob.
 3744        ///
 3745        /// For more information, see
 3746        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/get-blob-tags">
 3747        /// Get Blob Tags</see>
 3748        /// </summary>
 3749        /// <param name="conditions">
 3750        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3751        /// getting the blob's tags.  Note that TagConditions is currently the
 3752        /// only condition supported by GetTags.
 3753        /// </param>
 3754        /// <param name="cancellationToken">
 3755        /// Optional <see cref="CancellationToken"/> to propagate
 3756        /// notifications that the operation should be cancelled.
 3757        /// </param>
 3758        /// <returns>
 3759        /// A <see cref="Response{Tags}"/> on successfully getting tags.
 3760        /// </returns>
 3761        /// <remarks>
 3762        /// A <see cref="RequestFailedException"/> will be thrown if
 3763        /// a failure occurs.
 3764        /// </remarks>
 3765        public virtual Response<GetBlobTagResult> GetTags(
 3766            BlobRequestConditions conditions = default,
 3767            CancellationToken cancellationToken = default) =>
 303768            GetTagsInternal(
 303769                conditions: conditions,
 303770                async: false,
 303771                cancellationToken: cancellationToken)
 303772            .EnsureCompleted();
 3773
 3774        /// <summary>
 3775        /// Gets the tags associated with the underlying blob.
 3776        ///
 3777        /// For more information, see
 3778        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/get-blob-tags">
 3779        /// Get Blob Tags</see>
 3780        /// </summary>
 3781        /// <param name="conditions">
 3782        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3783        /// getting the blob's tags.  Note that TagConditions is currently the
 3784        /// only condition supported by GetTags.
 3785        /// </param>
 3786        /// <param name="cancellationToken">
 3787        /// Optional <see cref="CancellationToken"/> to propagate
 3788        /// notifications that the operation should be cancelled.
 3789        /// </param>
 3790        /// <returns>
 3791        /// A <see cref="Response{Tags}"/> on successfully getting tags.
 3792        /// </returns>
 3793        /// <remarks>
 3794        /// A <see cref="RequestFailedException"/> will be thrown if
 3795        /// a failure occurs.
 3796        /// </remarks>
 3797        public virtual async Task<Response<GetBlobTagResult>> GetTagsAsync(
 3798            BlobRequestConditions conditions = default,
 3799            CancellationToken cancellationToken = default) =>
 543800            await GetTagsInternal(
 543801                conditions: conditions,
 543802                async: true,
 543803                cancellationToken: cancellationToken)
 543804            .ConfigureAwait(false);
 3805
 3806        /// <summary>
 3807        /// Gets the tags associated with the underlying blob.
 3808        ///
 3809        /// For more information, see
 3810        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/get-blob-tags">
 3811        /// Get Blob Tags</see>
 3812        /// </summary>
 3813        /// <param name="async">
 3814        /// Whether to invoke the operation asynchronously.
 3815        /// </param>
 3816        /// <param name="conditions">
 3817        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3818        /// getting the blob's tags.  Note that TagConditions is currently the
 3819        /// only condition supported by GetTags.
 3820        /// </param>
 3821        /// <param name="cancellationToken">
 3822        /// Optional <see cref="CancellationToken"/> to propagate
 3823        /// notifications that the operation should be cancelled.
 3824        /// </param>
 3825        /// <returns>
 3826        /// A <see cref="Response{Tags}"/> on successfully getting tags.
 3827        /// </returns>
 3828        /// <remarks>
 3829        /// A <see cref="RequestFailedException"/> will be thrown if
 3830        /// a failure occurs.
 3831        /// </remarks>
 3832        private async Task<Response<GetBlobTagResult>> GetTagsInternal(
 3833            bool async,
 3834            BlobRequestConditions conditions,
 3835            CancellationToken cancellationToken)
 3836        {
 843837            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 3838            {
 3839                Pipeline.LogMethodEnter(
 3840                    nameof(BlobBaseClient),
 3841                    message:
 3842                    $"{nameof(Uri)}: {Uri}");
 3843
 3844                try
 3845                {
 843846                    Response<BlobTags> response = await BlobRestClient.Blob.GetTagsAsync(
 843847                        clientDiagnostics: ClientDiagnostics,
 843848                        pipeline: Pipeline,
 843849                        resourceUri: Uri,
 843850                        version: Version.ToVersionString(),
 843851                        ifTags: conditions?.TagConditions,
 843852                        async: async,
 843853                        operationName: $"{nameof(BlobBaseClient)}.{nameof(GetTags)}",
 843854                        cancellationToken: cancellationToken)
 843855                        .ConfigureAwait(false);
 3856
 723857                    GetBlobTagResult result = new GetBlobTagResult
 723858                    {
 723859                        Tags = response.Value.ToTagDictionary()
 723860                    };
 3861
 723862                    return Response.FromValue(
 723863                        result,
 723864                        response.GetRawResponse());
 3865                }
 123866                catch (Exception ex)
 3867                {
 3868                    Pipeline.LogException(ex);
 123869                    throw;
 3870                }
 3871                finally
 3872                {
 3873                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 3874                }
 3875            }
 723876        }
 3877        #endregion
 3878
 3879        #region SetTags
 3880        /// <summary>
 3881        /// Sets tags on the underlying blob.
 3882        /// A blob can have up to 10 tags.  Tag keys must be between 1 and 128 characters.  Tag values must be between 0
 3883        /// Valid tag key and value characters include lower and upper case letters, digits (0-9),
 3884        /// space (' '), plus ('+'), minus ('-'), period ('.'), foward slash ('/'), colon (':'), equals ('='), and under
 3885        ///
 3886        /// For more information, see
 3887        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/set-blob-tags">
 3888        /// Set Blob Tags</see>.
 3889        /// </summary>
 3890        /// <param name="tags">
 3891        /// The tags to set on the blob.
 3892        /// </param>
 3893        /// <param name="conditions">
 3894        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3895        /// setting the blob's tags.  Note that TagConditions is currently the
 3896        /// only condition supported by SetTags.
 3897        /// </param>
 3898        /// <param name="cancellationToken">
 3899        /// Optional <see cref="CancellationToken"/> to propagate
 3900        /// notifications that the operation should be cancelled.
 3901        /// </param>
 3902        /// <returns>
 3903        /// A <see cref="Response"/> on successfully setting the blob tags..
 3904        /// </returns>
 3905        /// <remarks>
 3906        /// A <see cref="RequestFailedException"/> will be thrown if
 3907        /// a failure occurs.
 3908        /// </remarks>
 3909        public virtual Response SetTags(
 3910            Tags tags,
 3911            BlobRequestConditions conditions = default,
 3912            CancellationToken cancellationToken = default) =>
 783913            SetTagsInternal(
 783914                tags: tags,
 783915                conditions: conditions,
 783916                async: false,
 783917                cancellationToken: cancellationToken)
 783918            .EnsureCompleted();
 3919
 3920        /// <summary>
 3921        /// Sets tags on the underlying blob.
 3922        /// A blob can have up to 10 tags.  Tag keys must be between 1 and 128 characters.  Tag values must be between 0
 3923        /// Valid tag key and value characters include lower and upper case letters, digits (0-9),
 3924        /// space (' '), plus ('+'), minus ('-'), period ('.'), foward slash ('/'), colon (':'), equals ('='), and under
 3925        ///
 3926        /// For more information, see
 3927        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/set-blob-tags">
 3928        /// Set Blob Tags</see>.
 3929        /// </summary>
 3930        /// <param name="tags">
 3931        /// The tags to set on the blob.
 3932        /// </param>
 3933        /// <param name="conditions">
 3934        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3935        /// setting the blob's tags.  Note that TagConditions is currently the
 3936        /// only condition supported by SetTags.
 3937        /// </param>
 3938        /// <param name="cancellationToken">
 3939        /// Optional <see cref="CancellationToken"/> to propagate
 3940        /// notifications that the operation should be cancelled.
 3941        /// </param>
 3942        /// <returns>
 3943        /// A <see cref="Response"/> on successfully setting the blob tags..
 3944        /// </returns>
 3945        /// <remarks>
 3946        /// A <see cref="RequestFailedException"/> will be thrown if
 3947        /// a failure occurs.
 3948        /// </remarks>
 3949        public virtual async Task<Response> SetTagsAsync(
 3950            Tags tags,
 3951            BlobRequestConditions conditions = default,
 3952            CancellationToken cancellationToken = default) =>
 1223953            await SetTagsInternal(
 1223954                tags: tags,
 1223955                conditions: conditions,
 1223956                async: true,
 1223957                cancellationToken: cancellationToken)
 1223958            .ConfigureAwait(false);
 3959
 3960        /// <summary>
 3961        /// Sets tags on the underlying blob.
 3962        /// A blob can have up to 10 tags.  Tag keys must be between 1 and 128 characters.  Tag values must be between 0
 3963        /// Valid tag key and value characters include lower and upper case letters, digits (0-9),
 3964        /// space (' '), plus ('+'), minus ('-'), period ('.'), foward slash ('/'), colon (':'), equals ('='), and under
 3965        ///
 3966        /// For more information, see
 3967        /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/set-blob-tags">
 3968        /// Set Blob Tags</see>.
 3969        /// </summary>
 3970        /// <param name="tags">
 3971        /// The tags to set on the blob.
 3972        /// </param>
 3973        /// <param name="conditions">
 3974        /// Optional <see cref="BlobRequestConditions"/> to add conditions on
 3975        /// setting the blob's tags.  Note that TagConditions is currently the
 3976        /// only condition supported by SetTags.
 3977        /// </param>
 3978        /// <param name="async">
 3979        /// Whether to invoke the operation asynchronously.
 3980        /// </param>
 3981        /// <param name="cancellationToken">
 3982        /// Optional <see cref="CancellationToken"/> to propagate
 3983        /// notifications that the operation should be cancelled.
 3984        /// </param>
 3985        /// <returns>
 3986        /// A <see cref="Response"/> on successfully setting the blob tags..
 3987        /// </returns>
 3988        /// <remarks>
 3989        /// A <see cref="RequestFailedException"/> will be thrown if
 3990        /// a failure occurs.
 3991        /// </remarks>
 3992        //TODO what about content CRC and content MD5?
 3993        private async Task<Response> SetTagsInternal(
 3994            Tags tags,
 3995            BlobRequestConditions conditions,
 3996            bool async,
 3997            CancellationToken cancellationToken)
 3998        {
 2003999            using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
 4000            {
 4001                Pipeline.LogMethodEnter(
 4002                    nameof(BlobBaseClient),
 4003                    message:
 4004                    $"{nameof(Uri)}: {Uri}\n" +
 4005                    $"{nameof(tags)}: {tags}");
 4006                try
 4007                {
 2004008                    return await BlobRestClient.Blob.SetTagsAsync(
 2004009                        clientDiagnostics: ClientDiagnostics,
 2004010                        pipeline: Pipeline,
 2004011                        resourceUri: Uri,
 2004012                        version: Version.ToVersionString(),
 2004013                        tags: tags.ToBlobTags(),
 2004014                        ifTags: conditions?.TagConditions,
 2004015                        async: async,
 2004016                        operationName: $"{nameof(BlobBaseClient)}.{nameof(SetTags)}",
 2004017                        cancellationToken: cancellationToken)
 2004018                        .ConfigureAwait(false);
 4019                }
 284020                catch (Exception ex)
 4021                {
 4022                    Pipeline.LogException(ex);
 284023                    throw;
 4024                }
 4025                finally
 4026                {
 4027                    Pipeline.LogMethodExit(nameof(BlobBaseClient));
 4028                }
 4029            }
 1724030        }
 4031        #endregion
 4032    }
 4033
 4034    /// <summary>
 4035    /// Add easy to discover methods to <see cref="BlobContainerClient"/> for
 4036    /// creating <see cref="BlobBaseClient"/> instances.
 4037    /// </summary>
 4038    public static partial class SpecializedBlobExtensions
 4039    {
 4040        /// <summary>
 4041        /// Create a new <see cref="BlobBaseClient"/> object by concatenating
 4042        /// <paramref name="blobName"/> to the end of the
 4043        /// <paramref name="client"/>'s <see cref="BlobContainerClient.Uri"/>.
 4044        /// The new <see cref="BlobBaseClient"/> uses the same request policy
 4045        /// pipeline as the <see cref="BlobContainerClient"/>.
 4046        /// </summary>
 4047        /// <param name="client">The <see cref="BlobContainerClient"/>.</param>
 4048        /// <param name="blobName">The name of the blob.</param>
 4049        /// <returns>A new <see cref="BlobBaseClient"/> instance.</returns>
 4050        public static BlobBaseClient GetBlobBaseClient(
 4051            this BlobContainerClient client,
 4052            string blobName) =>
 4053            new BlobBaseClient(
 4054                client.Uri.AppendToPath(blobName),
 4055                client.Pipeline,
 4056                client.Version,
 4057                client.ClientDiagnostics,
 4058                client.CustomerProvidedKey,
 4059                client.ClientSideEncryption,
 4060                client.EncryptionScope);
 4061
 4062        /// <summary>
 4063        /// Creates a new instance of the <see cref="BlobClient"/> class, maintaining all the same
 4064        /// internals but specifying new <see cref="ClientSideEncryptionOptions"/>.
 4065        /// </summary>
 4066        /// <param name="client">Client to base off of.</param>
 4067        /// <param name="clientSideEncryptionOptions">New encryption options. Setting this to <code>default</code> will 
 4068        /// <returns>New instance with provided options and same internals otherwise.</returns>
 4069        public static BlobClient WithClientSideEncryptionOptions(this BlobClient client, ClientSideEncryptionOptions cli
 4070            => new BlobClient(
 4071                client.Uri,
 4072                client.Pipeline,
 4073                client.Version,
 4074                client.ClientDiagnostics,
 4075                client.CustomerProvidedKey,
 4076                clientSideEncryptionOptions,
 4077                client.EncryptionScope);
 4078    }
 4079}

Methods/Properties

get_Uri()
get_Pipeline()
get_Version()
get_ClientDiagnostics()
get_CustomerProvidedKey()
get_ClientSideEncryption()
get_UsingClientSideEncryption()
get_EncryptionScope()
get_AccountName()
get_BlobContainerName()
get_Name()
.ctor()
.ctor(...)
.ctor(...)
.ctor(...)
.ctor(...)
.ctor(...)
.ctor(...)
.ctor(...)
WithSnapshot(...)
WithSnapshotCore(...)
WithVersion(...)
WithVersionCore(...)
SetNameFieldsIfNull()
Download()
DownloadAsync()
Download(...)
DownloadAsync()
Download(...)
DownloadAsync()
DownloadInternal()
<DownloadInternal()
StartDownloadAsync()
DownloadTo(...)
DownloadTo(...)
DownloadToAsync()
DownloadToAsync()
DownloadTo(...)
DownloadTo(...)
DownloadToAsync()
DownloadToAsync()
DownloadTo(...)
DownloadTo(...)
DownloadToAsync()
DownloadToAsync()
StagedDownloadAsync()
OpenRead(...)
OpenRead(...)
OpenReadAsync()
OpenReadAsync()
OpenReadInternal()
StartCopyFromUri(...)
StartCopyFromUri(...)
StartCopyFromUriAsync()
StartCopyFromUriAsync()
StartCopyFromUriInternal()
AbortCopyFromUri(...)
AbortCopyFromUriAsync()
AbortCopyFromUriInternal()
SyncCopyFromUri(...)
SyncCopyFromUriAsync()
SyncCopyFromUriInternal()
Delete(...)
DeleteAsync()
DeleteIfExists(...)
DeleteIfExistsAsync()
DeleteIfExistsInternal()
DeleteInternal()
Exists(...)
ExistsAsync()
ExistsInternal()
Undelete(...)
UndeleteAsync()
UndeleteInternal()
GetProperties(...)
GetPropertiesAsync()
GetPropertiesInternal()
SetHttpHeaders(...)
SetHttpHeadersAsync()
SetHttpHeadersInternal()
SetMetadata(...)
SetMetadataAsync()
SetMetadataInternal()
CreateSnapshot(...)
CreateSnapshotAsync()
CreateSnapshotInternal()
SetAccessTier(...)
SetAccessTierAsync()
SetAccessTierInternal()
GetTags(...)
GetTagsAsync()
GetTagsInternal()
SetTags(...)
SetTagsAsync()
SetTagsInternal()