public BlockBlobWriteStream( BlockBlobClient blockBlobClient, long bufferSize, long position, BlobRequestConditions conditions, IProgress <long> progressHandler, BlobHttpHeaders blobHttpHeaders, IDictionary <string, string> metadata, IDictionary <string, string> tags // TODO #27253 //UploadTransactionalHashingOptions hashingOptions ) : base( position, bufferSize, progressHandler //hashingOptions ) { ValidateBufferSize(bufferSize); _blockBlobClient = blockBlobClient; _conditions = conditions ?? new BlobRequestConditions(); _blockIds = new List <string>(); _blobHttpHeaders = blobHttpHeaders; _metadata = metadata; _tags = tags; }
public async Task RenameBlobContainerAsync_SourceLease() { // Arrange BlobServiceClient service = GetServiceClient_SharedKey(); string oldContainerName = GetNewContainerName(); string newContainerName = GetNewContainerName(); BlobContainerClient container = InstrumentClient(service.GetBlobContainerClient(oldContainerName)); await container.CreateAsync(); string leaseId = Recording.Random.NewGuid().ToString(); BlobLeaseClient leaseClient = InstrumentClient(container.GetBlobLeaseClient(leaseId)); await leaseClient.AcquireAsync(duration : TimeSpan.FromSeconds(30)); BlobRequestConditions sourceConditions = new BlobRequestConditions { LeaseId = leaseId }; // Act BlobContainerClient newContainer = await service.RenameBlobContainerAsync( sourceContainerName : oldContainerName, destinationContainerName : newContainerName, sourceConditions : sourceConditions); // Assert await newContainer.GetPropertiesAsync(); // Cleanup await newContainer.DeleteAsync(); }
public async Task RenameBlobContainerAsync_SourceLeaseFailed() { // Arrange BlobServiceClient service = GetServiceClient_SharedKey(); string oldContainerName = GetNewContainerName(); string newContainerName = GetNewContainerName(); BlobContainerClient container = InstrumentClient(service.GetBlobContainerClient(oldContainerName)); await container.CreateAsync(); string leaseId = Recording.Random.NewGuid().ToString(); BlobRequestConditions sourceConditions = new BlobRequestConditions { LeaseId = leaseId }; // Act await TestHelper.AssertExpectedExceptionAsync <RequestFailedException>( service.RenameBlobContainerAsync( sourceContainerName: oldContainerName, destinationContainerName: newContainerName, sourceConditions: sourceConditions), e => Assert.AreEqual(BlobErrorCode.LeaseNotPresentWithContainerOperation.ToString(), e.ErrorCode)); // Cleanup await container.DeleteAsync(); }
public async Task QueryAsync_AccessConditionsFail() { var garbageLeaseId = GetGarbageLeaseId(); foreach (AccessConditionParameters parameters in GetAccessConditionsFail_Data(garbageLeaseId)) { // Arrange await using DisposingContainer test = await GetTestContainerAsync(); BlockBlobClient blockBlobClient = InstrumentClient(test.Container.GetBlockBlobClient(GetNewBlobName())); Stream stream = CreateDataStream(Constants.KB); await blockBlobClient.UploadAsync(stream); parameters.NoneMatch = await SetupBlobMatchCondition(blockBlobClient, parameters.NoneMatch); BlobRequestConditions accessConditions = BuildAccessConditions(parameters); BlobQueryOptions options = new BlobQueryOptions { Conditions = accessConditions }; string query = @"SELECT * from BlobStorage"; // Act await TestHelper.AssertExpectedExceptionAsync <RequestFailedException>( blockBlobClient.QueryAsync( query, options), e => { }); } }
public async Task SetImmutibilityPolicyAsync_IfModifiedSince() { // Arrange BlobBaseClient blob = await GetNewBlobClient(_containerClient); BlobImmutabilityPolicy immutabilityPolicy = new BlobImmutabilityPolicy { ExpiresOn = Recording.UtcNow.AddMinutes(5), PolicyMode = BlobImmutabilityPolicyMode.Unlocked }; // The service rounds Immutability Policy Expiry to the nearest second. DateTimeOffset expectedImmutabilityPolicyExpiry = RoundToNearestSecond(immutabilityPolicy.ExpiresOn.Value); BlobRequestConditions conditions = new BlobRequestConditions { IfUnmodifiedSince = Recording.UtcNow.AddDays(1) }; // Act Response <BlobImmutabilityPolicy> response = await blob.SetImmutabilityPolicyAsync( immutabilityPolicy : immutabilityPolicy, conditions : conditions); // Assert Assert.AreEqual(expectedImmutabilityPolicyExpiry, response.Value.ExpiresOn); Assert.AreEqual(immutabilityPolicy.PolicyMode, response.Value.PolicyMode); }
public override async Task <OriginalData> GetAsync(string source, ICachedImage existingCachedImage) { BlobClient blob = Client.GetBlobClient(source); BlobRequestConditions conditions = new BlobRequestConditions(); if (existingCachedImage != null) { conditions.IfNoneMatch = new ETag(existingCachedImage.Metadata.Cache.ETag); } var response = await blob.DownloadAsync(conditions : conditions); if (response.GetRawResponse().Status == (int)System.Net.HttpStatusCode.NotModified) { return(null); } return(new OriginalData( response.Value.ContentType, await response.Value.Content.ToByteArrayAsync(), new CacheSettings() { ETag = response.Value.Details.ETag.ToString().GetTagUnquoted() })); }
public virtual async Task <Response <BlobContentInfo> > UploadAsync( string path, BlobHttpHeaders httpHeaders = default, Metadata metadata = default, BlobRequestConditions conditions = default, IProgress <long> progressHandler = default, AccessTier?accessTier = default, StorageTransferOptions transferOptions = default, CancellationToken cancellationToken = default) { using (FileStream stream = new FileStream(path, FileMode.Open)) { return(await StagedUploadAsync( stream, httpHeaders, metadata, conditions, progressHandler, accessTier, transferOptions : transferOptions, async : true, cancellationToken : cancellationToken) .ConfigureAwait(false)); } }
/// <summary> /// This operation will create a new /// block blob of arbitrary size by uploading it as indiviually staged /// blocks if it's larger than the /// <paramref name="singleUploadThreshold"/>. /// </summary> /// <param name="content"> /// A <see cref="Stream"/> containing the content to upload. /// </param> /// <param name="blobHttpHeaders"> /// Optional standard HTTP header properties that can be set for the /// block blob. /// </param> /// <param name="metadata"> /// Optional custom metadata to set for this block blob. /// </param> /// <param name="conditions"> /// Optional <see cref="BlobRequestConditions"/> to add conditions on /// the creation of this new block blob. /// </param> /// <param name="progressHandler"> /// Optional <see cref="IProgress{Long}"/> to provide /// progress updates about data transfers. /// </param> /// <param name="accessTier"> /// Optional <see cref="AccessTier"/> /// Indicates the tier to be set on the blob. /// </param> /// <param name="singleUploadThreshold"> /// The maximum size stream that we'll upload as a single block. The /// default value is 256MB. /// </param> /// <param name="transferOptions"> /// Optional <see cref="StorageTransferOptions"/> to configure /// parallel transfer behavior. /// </param> /// <param name="async"> /// </param> /// <param name="cancellationToken"> /// Optional <see cref="CancellationToken"/> to propagate /// notifications that the operation should be cancelled. /// </param> /// <returns> /// A <see cref="Response{BlobContentInfo}"/> describing the /// state of the updated block blob. /// </returns> /// <remarks> /// A <see cref="RequestFailedException"/> will be thrown if /// a failure occurs. /// </remarks> internal async Task <Response <BlobContentInfo> > StagedUploadAsync( Stream content, BlobHttpHeaders blobHttpHeaders, Metadata metadata, BlobRequestConditions conditions, IProgress <long> progressHandler, AccessTier?accessTier = default, long?singleUploadThreshold = default, StorageTransferOptions transferOptions = default, bool async = true, CancellationToken cancellationToken = default) { var client = new BlockBlobClient(Uri, Pipeline, ClientDiagnostics, CustomerProvidedKey); singleUploadThreshold ??= client.BlockBlobMaxUploadBlobBytes; Debug.Assert(singleUploadThreshold <= client.BlockBlobMaxUploadBlobBytes); var uploader = new PartitionedUploader(client, transferOptions, singleUploadThreshold); if (async) { return(await uploader.UploadAsync(content, blobHttpHeaders, metadata, conditions, progressHandler, accessTier, cancellationToken).ConfigureAwait(false)); } else { return(uploader.Upload(content, blobHttpHeaders, metadata, conditions, progressHandler, accessTier, cancellationToken)); } }
/// <summary> /// This operation will create a new /// block blob of arbitrary size by uploading it as indiviually staged /// blocks if it's larger than the /// <paramref name="singleUploadThreshold"/>. /// </summary> /// <param name="path"> /// A file path of the file to upload. /// </param> /// <param name="blobHttpHeaders"> /// Optional standard HTTP header properties that can be set for the /// block blob. /// </param> /// <param name="metadata"> /// Optional custom metadata to set for this block blob. /// </param> /// <param name="conditions"> /// Optional <see cref="BlobRequestConditions"/> to add conditions on /// the creation of this new block blob. /// </param> /// <param name="progressHandler"> /// Optional <see cref="IProgress{Long}"/> to provide /// progress updates about data transfers. /// </param> /// <param name="accessTier"> /// Optional <see cref="AccessTier"/> /// Indicates the tier to be set on the blob. /// </param> /// <param name="singleUploadThreshold"> /// The maximum size stream that we'll upload as a single block. The /// default value is 256MB. /// </param> /// <param name="transferOptions"> /// Optional <see cref="StorageTransferOptions"/> to configure /// parallel transfer behavior. /// </param> /// <param name="async"> /// </param> /// <param name="cancellationToken"> /// Optional <see cref="CancellationToken"/> to propagate /// notifications that the operation should be cancelled. /// </param> /// <returns> /// A <see cref="Response{BlobContentInfo}"/> describing the /// state of the updated block blob. /// </returns> /// <remarks> /// A <see cref="RequestFailedException"/> will be thrown if /// a failure occurs. /// </remarks> internal async Task <Response <BlobContentInfo> > StagedUploadAsync( string path, BlobHttpHeaders blobHttpHeaders, Metadata metadata, BlobRequestConditions conditions, IProgress <long> progressHandler, AccessTier?accessTier = default, long?singleUploadThreshold = default, StorageTransferOptions transferOptions = default, bool async = true, CancellationToken cancellationToken = default) { using (FileStream stream = new FileStream(path, FileMode.Open)) { return(await StagedUploadAsync( stream, blobHttpHeaders, metadata, conditions, progressHandler, accessTier, singleUploadThreshold : singleUploadThreshold, transferOptions : transferOptions, async : async, cancellationToken : cancellationToken) .ConfigureAwait(false)); } }
/// <summary> /// This operation will create a new /// block blob of arbitrary size by uploading it as indiviually staged /// blocks if it's larger than the /// <paramref name="transferOptions"/> MaximumTransferLength. /// </summary> /// <param name="content"> /// A <see cref="Stream"/> containing the content to upload. /// </param> /// <param name="blobHttpHeaders"> /// Optional standard HTTP header properties that can be set for the /// block blob. /// </param> /// <param name="metadata"> /// Optional custom metadata to set for this block blob. /// </param> /// <param name="conditions"> /// Optional <see cref="BlobRequestConditions"/> to add conditions on /// the creation of this new block blob. /// </param> /// <param name="progressHandler"> /// Optional <see cref="IProgress{Long}"/> to provide /// progress updates about data transfers. /// </param> /// <param name="accessTier"> /// Optional <see cref="AccessTier"/> /// Indicates the tier to be set on the blob. /// </param> /// <param name="transferOptions"> /// Optional <see cref="StorageTransferOptions"/> to configure /// parallel transfer behavior. /// </param> /// <param name="async"> /// </param> /// <param name="cancellationToken"> /// Optional <see cref="CancellationToken"/> to propagate /// notifications that the operation should be cancelled. /// </param> /// <returns> /// A <see cref="Response{BlobContentInfo}"/> describing the /// state of the updated block blob. /// </returns> /// <remarks> /// A <see cref="RequestFailedException"/> will be thrown if /// a failure occurs. /// </remarks> internal async Task <Response <BlobContentInfo> > StagedUploadAsync( Stream content, BlobHttpHeaders blobHttpHeaders, Metadata metadata, BlobRequestConditions conditions, IProgress <long> progressHandler, AccessTier?accessTier = default, StorageTransferOptions transferOptions = default, bool async = true, CancellationToken cancellationToken = default) { if (UsingClientSideEncryption) { // content is now unseekable, so PartitionedUploader will be forced to do a buffered multipart upload (content, metadata) = await new BlobClientSideEncryptor(new ClientSideEncryptor(ClientSideEncryption)) .ClientSideEncryptInternal(content, metadata, async, cancellationToken).ConfigureAwait(false); } var client = new BlockBlobClient(Uri, Pipeline, Version, ClientDiagnostics, CustomerProvidedKey, EncryptionScope); PartitionedUploader uploader = new PartitionedUploader( client, transferOptions, operationName: $"{nameof(BlobClient)}.{nameof(Upload)}"); if (async) { return(await uploader.UploadAsync(content, blobHttpHeaders, metadata, conditions, progressHandler, accessTier, cancellationToken).ConfigureAwait(false)); } else { return(uploader.Upload(content, blobHttpHeaders, metadata, conditions, progressHandler, accessTier, cancellationToken)); } }
/// <summary> /// The <see cref="Upload(string, BlobHttpHeaders, Metadata, BlobRequestConditions, IProgress{long}, AccessTier?, StorageTransferOptions, CancellationToken)"/> /// operation creates a new block blob or updates the content of an /// existing block blob. Updating an existing block blob overwrites /// any existing metadata on the blob. /// /// For partial block blob updates and other advanced features, please /// see <see cref="BlockBlobClient"/>. To create or modify page or /// append blobs, please see <see cref="PageBlobClient"/> or /// <see cref="AppendBlobClient"/>. /// /// For more information, see <see href="https://docs.microsoft.com/rest/api/storageservices/put-blob" />. /// </summary> /// <param name="path"> /// A file path containing the content to upload. /// </param> /// <param name="httpHeaders"> /// Optional standard HTTP header properties that can be set for the /// block blob. /// </param> /// <param name="metadata"> /// Optional custom metadata to set for this block blob. /// </param> /// <param name="conditions"> /// Optional <see cref="BlobRequestConditions"/> to add conditions on /// the creation of this new block blob. /// </param> /// <param name="progressHandler"> /// Optional <see cref="IProgress{Long}"/> to provide /// progress updates about data transfers. /// </param> /// <param name="accessTier"> /// Optional <see cref="AccessTier"/> /// Indicates the tier to be set on the blob. /// </param> /// <param name="transferOptions"> /// Optional <see cref="StorageTransferOptions"/> to configure /// parallel transfer behavior. /// </param> /// <param name="cancellationToken"> /// Optional <see cref="CancellationToken"/> to propagate /// notifications that the operation should be cancelled. /// </param> /// <returns> /// A <see cref="Response{BlobContentInfo}"/> describing the /// state of the updated block blob. /// </returns> /// <remarks> /// A <see cref="RequestFailedException"/> will be thrown if /// a failure occurs. /// </remarks> public virtual Response <BlobContentInfo> Upload( string path, BlobHttpHeaders httpHeaders = default, Metadata metadata = default, BlobRequestConditions conditions = default, IProgress <long> progressHandler = default, AccessTier?accessTier = default, StorageTransferOptions transferOptions = default, CancellationToken cancellationToken = default) { using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { return(StagedUploadAsync( stream, httpHeaders, metadata, conditions, progressHandler, accessTier, transferOptions: transferOptions, async: false, cancellationToken: cancellationToken) .EnsureCompleted()); } }
private static BlobRequestConditions CreateConditionsWithEtag(BlobRequestConditions conditions, ETag etag) => new BlobRequestConditions { LeaseId = conditions?.LeaseId, IfMatch = conditions?.IfMatch ?? etag, IfNoneMatch = conditions?.IfNoneMatch, IfModifiedSince = conditions?.IfModifiedSince, IfUnmodifiedSince = conditions?.IfUnmodifiedSince };
public AzureWriteBlockBlobStream(BlockBlobClient blob, BlobRequestConditions condition, IDictionary <string, string> metadata) { _blob = blob; _condition = condition; _metadata = metadata; _buff = new MemoryStream(); _partNumber = 1; }
protected override Task <Stream> OpenWriteAsync( AppendBlobClient client, bool overwrite, long?maxDataSize, int?bufferSize = null, BlobRequestConditions conditions = null, Dictionary <string, string> metadata = null, HttpHeaderParameters httpHeaders = null, IProgress <long> progressHandler = null) => OpenWriteAsync(client, overwrite, maxDataSize, tags: default, bufferSize, conditions, metadata, httpHeaders, progressHandler);
/// <summary> /// Calls this client's open-write method. /// </summary> /// <param name="client">Client to call the download on.</param> protected abstract Task <Stream> OpenWriteAsync( TBlobClient client, bool overwrite, long?maxDataSize, Dictionary <string, string> tags, int?bufferSize = default, BlobRequestConditions conditions = default, Dictionary <string, string> metadata = default, HttpHeaderParameters httpHeaders = default, IProgress <long> progressHandler = default);
/// <summary> /// Rotates the Key Encryption Key (KEK) for a client-side encrypted blob without /// needing to reupload the entire blob. /// </summary> /// <param name="client"> /// Client to the blob. /// </param> /// <param name="encryptionOptionsOverride"> /// Optional override for client-side encryption options to use when updating the key encryption key. /// Defaults to the <see cref="ClientSideEncryptionOptions"/> configured on the client when this is /// not populated. New key encryption key for the blob will be the /// <see cref="ClientSideEncryptionOptions.KeyEncryptionKey"/> on whichever encryption options are /// used for the operation. Options must have a resolver that can resolve the old key on the blob. /// </param> /// <param name="conditions"> /// Optional request conditions for the operation. /// </param> /// <param name="cancellationToken"> /// Cancellation token for the operation. /// </param> public static void UpdateClientSideKeyEncryptionKey( this BlobClient client, ClientSideEncryptionOptions encryptionOptionsOverride = default, BlobRequestConditions conditions = default, CancellationToken cancellationToken = default) => UpdateClientsideKeyEncryptionKeyInternal( client, encryptionOptionsOverride, conditions, async: false, cancellationToken).EnsureCompleted();
public async ValueTask <IDictionary <string, string> > GetMetadataAsync(string leaseId, CancellationToken cancellationToken) { var conditions = new BlobRequestConditions { LeaseId = leaseId }; var properties = SyncViaAsync.IsSynchronous ? this._blobClient.GetProperties(conditions, cancellationToken) : await this._blobClient.GetPropertiesAsync(conditions, cancellationToken).ConfigureAwait(false); return(properties.Value.Metadata); }
/// <summary> /// Rotates the Key Encryption Key (KEK) for a client-side encrypted blob without /// needing to reupload the entire blob. /// </summary> /// <param name="client"> /// Client to the blob. /// </param> /// <param name="encryptionOptionsOverride"> /// Optional override for client-side encryption options to use when updating the key encryption key. /// Defaults to the <see cref="ClientSideEncryptionOptions"/> configured on the client when this is /// not populated. New key encryption key for the blob will be the /// <see cref="ClientSideEncryptionOptions.KeyEncryptionKey"/> on whichever encryption options are /// used for the operation. Options must have a resolver that can resolve the old key on the blob. /// </param> /// <param name="conditions"> /// Optional request conditions for the operation. /// </param> /// <param name="cancellationToken"> /// Cancellation token for the operation. /// </param> public static async Task UpdateClientSideKeyEncryptionKeyAsync( this BlobClient client, ClientSideEncryptionOptions encryptionOptionsOverride = default, BlobRequestConditions conditions = default, CancellationToken cancellationToken = default) => await UpdateClientsideKeyEncryptionKeyInternal( client, encryptionOptionsOverride, conditions, async : true, cancellationToken).ConfigureAwait(false);
/// <summary> /// The <see cref="DeleteBlob(Uri, DeleteSnapshotsOption, BlobRequestConditions)"/> /// operation marks the specified blob or snapshot for deletion. The /// blob is later deleted during garbage collection. /// /// Note that in order to delete a blob, you must delete all of its /// snapshots. You can delete both at the same time using /// <see cref="DeleteSnapshotsOption.IncludeSnapshots"/>. /// /// For more information, see /// <see href="https://docs.microsoft.com/rest/api/storageservices/delete-blob">Delete Blob</see>. /// </summary> /// <param name="blobUri"> /// The blob to delete's primary <see cref="Uri"/> endpoint. /// </param> /// <param name="snapshotsOption"> /// Specifies options for deleting blob snapshots. /// </param> /// <param name="conditions"> /// Optional <see cref="BlobRequestConditions"/> to add conditions on /// deleting this blob. /// </param> /// <returns> /// A <see cref="Response"/> on successfully deleting. The response /// cannot be used until the batch has been submitted with /// <see cref="BlobBatchClient.SubmitBatchAsync"/>. /// </returns> public virtual Response DeleteBlob( Uri blobUri, DeleteSnapshotsOption snapshotsOption = default, BlobRequestConditions conditions = default) { BlobUriBuilder uriBuilder = new BlobUriBuilder(blobUri); return(DeleteBlob( blobContainerName: uriBuilder.BlobContainerName, blobName: uriBuilder.BlobName, snapshotsOption: snapshotsOption, conditions: conditions)); }
/// <summary> /// Updates the checkpoint using the given information for the associated partition and consumer group in the storage blob service. /// </summary> /// /// <param name="checkpoint">The checkpoint containing the information to be stored.</param> /// /// <returns>A task to be resolved on when the operation has completed.</returns> /// public override async Task UpdateCheckpointAsync(Checkpoint checkpoint) { var blobName = $"{ checkpoint.FullyQualifiedNamespace }/{ checkpoint.EventHubName }/{ checkpoint.ConsumerGroup }/{ checkpoint.PartitionId }"; BlobClient blobClient = _containerClient.GetBlobClient(blobName); BlobProperties currentBlob; try { currentBlob = (await blobClient.GetPropertiesAsync().ConfigureAwait(false)).Value; } catch (RequestFailedException ex) when(ex.ErrorCode == BlobErrorCode.BlobNotFound) { Log($"Checkpoint with partition id = '{ checkpoint.PartitionId }' could not be updated because no associated ownership was found."); return; } // In case this key does not exist, ownerIdentifier is set to null. The OwnerIdentifier in Checkpoint cannot // be null as well, so we won't be able to update the associated ownership. currentBlob.Metadata.TryGetValue(BlobMetadataKey.OwnerIdentifier, out var ownerIdentifier); if (ownerIdentifier == checkpoint.OwnerIdentifier) { var metadata = new Dictionary <string, string>() { { BlobMetadataKey.OwnerIdentifier, checkpoint.OwnerIdentifier }, { BlobMetadataKey.Offset, checkpoint.Offset.ToString() }, { BlobMetadataKey.SequenceNumber, checkpoint.SequenceNumber.ToString() } }; var requestConditions = new BlobRequestConditions { IfMatch = currentBlob.ETag }; try { await blobClient.SetMetadataAsync(metadata, requestConditions).ConfigureAwait(false); Log($"Checkpoint with partition id = '{ checkpoint.PartitionId }' updated."); } catch (RequestFailedException ex) when(ex.ErrorCode == BlobErrorCode.ConditionNotMet) { Log($"Checkpoint with partition id = '{ checkpoint.PartitionId }' could not be updated because eTag has changed."); } } else { Log($"Checkpoint with partition id = '{ checkpoint.PartitionId }' could not be updated because owner has changed."); } }
public override Task <Response <BlobProperties> > GetPropertiesAsync(BlobRequestConditions conditions = null, CancellationToken cancellationToken = default) { if (GetPropertiesException != null) { throw GetPropertiesException; } if (Properties == null) { throw new RequestFailedException(404, BlobErrorCode.BlobNotFound.ToString(), BlobErrorCode.BlobNotFound.ToString(), default); } return(Task.FromResult(Response.FromValue(Properties, Mock.Of <Response>()))); }
public BlockBlobWriteStream( BlockBlobClient blockBlobClient, long bufferSize, long position, BlobRequestConditions conditions, IProgress <long> progressHandler) : base( position, bufferSize, progressHandler) { ValidateBufferSize(bufferSize); _blockBlobClient = blockBlobClient; _conditions = conditions ?? new BlobRequestConditions(); _blockIds = new List <string>(); }
/// <summary> /// The <see cref="SetBlobAccessTier(Uri, AccessTier, RehydratePriority?, BlobRequestConditions)"/> /// operation sets the tier on a blob. The operation is allowed on /// block blobs in a blob storage or general purpose v2 account. /// /// A block blob's tier determines Hot/Cool/Archive storage type. This /// operation does not update the blob's ETag. For detailed /// information about block blob level tiering /// <see href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-storage-tiers"> /// Blob Storage Tiers</see>. /// /// </summary> /// <param name="blobUri"> /// The blob's primary <see cref="Uri"/> endpoint. /// </param> /// <param name="accessTier"> /// Indicates the tier to be set on the blob. /// </param> /// <param name="rehydratePriority"> /// Optional <see cref="RehydratePriority"/> /// Indicates the priority with which to rehydrate an archived blob. /// </param> /// <param name="leaseAccessConditions"> /// Optional <see cref="BlobRequestConditions"/> to add conditions on /// setting the access tier. /// </param> /// <returns> /// A <see cref="Response"/> on successfully deleting. The response /// cannot be used until the batch has been submitted with /// <see cref="BlobBatchClient.SubmitBatchAsync"/>. /// </returns> public virtual Response SetBlobAccessTier( Uri blobUri, AccessTier accessTier, RehydratePriority?rehydratePriority = default, BlobRequestConditions leaseAccessConditions = default) { BlobUriBuilder uriBuilder = new BlobUriBuilder(blobUri); return(SetBlobAccessTier( blobContainerName: uriBuilder.BlobContainerName, blobName: uriBuilder.BlobName, accessTier: accessTier, rehydratePriority: rehydratePriority, leaseAccessConditions: leaseAccessConditions)); }
/// <summary> /// This operation will create a new /// block blob of arbitrary size by uploading it as indiviually staged /// blocks if it's larger than the /// <paramref name="transferOptions"/>. MaximumTransferLength. /// </summary> /// <param name="path"> /// A file path of the file to upload. /// </param> /// <param name="blobHttpHeaders"> /// Optional standard HTTP header properties that can be set for the /// block blob. /// </param> /// <param name="metadata"> /// Optional custom metadata to set for this block blob. /// </param> /// <param name="conditions"> /// Optional <see cref="BlobRequestConditions"/> to add conditions on /// the creation of this new block blob. /// </param> /// <param name="progressHandler"> /// Optional <see cref="IProgress{Long}"/> to provide /// progress updates about data transfers. /// </param> /// <param name="accessTier"> /// Optional <see cref="AccessTier"/> /// Indicates the tier to be set on the blob. /// </param> /// <param name="transferOptions"> /// Optional <see cref="StorageTransferOptions"/> to configure /// parallel transfer behavior. /// </param> /// <param name="async"> /// </param> /// <param name="cancellationToken"> /// Optional <see cref="CancellationToken"/> to propagate /// notifications that the operation should be cancelled. /// </param> /// <returns> /// A <see cref="Response{BlobContentInfo}"/> describing the /// state of the updated block blob. /// </returns> /// <remarks> /// A <see cref="RequestFailedException"/> will be thrown if /// a failure occurs. /// </remarks> internal async Task <Response <BlobContentInfo> > StagedUploadAsync( string path, BlobHttpHeaders blobHttpHeaders, Metadata metadata, BlobRequestConditions conditions, IProgress <long> progressHandler, AccessTier?accessTier = default, StorageTransferOptions transferOptions = default, bool async = true, CancellationToken cancellationToken = default) { // TODO Upload from file will get it's own implementation in the future that opens more // than one stream at once. This is incompatible with .NET's CryptoStream. We will // need to uncomment the below code and revert to upload from stream if client-side // encryption is enabled. //if (ClientSideEncryption != default) //{ // using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) // { // return await StagedUploadAsync( // stream, // blobHttpHeaders, // metadata, // conditions, // progressHandler, // accessTier, // transferOptions: transferOptions, // async: async, // cancellationToken: cancellationToken) // .ConfigureAwait(false); // } //} using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { return(await StagedUploadAsync( stream, blobHttpHeaders, metadata, conditions, progressHandler, accessTier, transferOptions : transferOptions, async : async, cancellationToken : cancellationToken) .ConfigureAwait(false)); } }
public async Task SetImmutibilityPolicyAsync_InvalidRequestConditions(string invalidCondition) { // Arrange BlobBaseClient blobBaseClient = new BlobBaseClient(new Uri("https://www.doesntmatter.com"), GetOptions()); BlobImmutabilityPolicy immutabilityPolicy = new BlobImmutabilityPolicy { ExpiresOn = Recording.UtcNow.AddMinutes(5), PolicyMode = BlobImmutabilityPolicyMode.Unlocked }; BlobRequestConditions conditions = new BlobRequestConditions(); switch (invalidCondition) { case nameof(BlobRequestConditions.IfMatch): conditions.IfMatch = new ETag(); break; case nameof(BlobRequestConditions.IfModifiedSince): conditions.IfModifiedSince = Recording.UtcNow.AddMinutes(5); break; case nameof(BlobRequestConditions.IfNoneMatch): conditions.IfNoneMatch = new ETag(); break; case nameof(BlobRequestConditions.LeaseId): conditions.LeaseId = string.Empty; break; case nameof(BlobRequestConditions.TagConditions): conditions.TagConditions = string.Empty; break; } // Act await TestHelper.AssertExpectedExceptionAsync <ArgumentException>( blobBaseClient.SetImmutabilityPolicyAsync( immutabilityPolicy, conditions), e => { Assert.IsTrue(e.Message.Contains($"SetImmutabilityPolicy does not support the {invalidCondition} condition(s).")); Assert.IsTrue(e.Message.Contains("conditions")); }); }
public Response <BlobContentInfo> Upload( Stream content, BlobHttpHeaders blobHttpHeaders, IDictionary <string, string> metadata, BlobRequestConditions conditions, IProgress <long> progressHandler, AccessTier?accessTier = default, CancellationToken cancellationToken = default) { // If we can compute the size and it's small enough if (PartitionedUploadExtensions.TryGetLength(content, out long length) && length < _singleUploadThreshold) { // Upload it in a single request return(_client.UploadInternal( content, blobHttpHeaders, metadata, conditions, accessTier, progressHandler, _operationName, false, cancellationToken).EnsureCompleted()); } // If the caller provided an explicit block size, we'll use it. // Otherwise we'll adjust dynamically based on the size of the // content. int blockSize = _blockSize != null ? _blockSize.Value : length < Constants.LargeUploadThreshold ? Constants.DefaultBufferSize : Constants.LargeBufferSize; // Otherwise stage individual blocks one at a time. It's not as // fast as a parallel upload, but you get the benefit of the retry // policy working on a single block instead of the entire stream. return(UploadInSequence( content, blockSize, blobHttpHeaders, metadata, conditions, progressHandler, accessTier, cancellationToken)); }
public async Task <Response <BlobContentInfo> > UploadAsync( Stream content, BlobHttpHeaders blobHttpHeaders, IDictionary <string, string> metadata, BlobRequestConditions conditions, IProgress <long> progressHandler, AccessTier?accessTier = default, CancellationToken cancellationToken = default) { // If we can compute the size and it's small enough if (PartitionedUploadExtensions.TryGetLength(content, out long length) && length < _singleUploadThreshold) { // Upload it in a single request return(await _client.UploadInternal( content, blobHttpHeaders, metadata, conditions, accessTier, progressHandler, _operationName, async : true, cancellationToken) .ConfigureAwait(false)); } // If the caller provided an explicit block size, we'll use it. // Otherwise we'll adjust dynamically based on the size of the // content. int blockSize = _blockSize != null ? _blockSize.Value : length < Constants.LargeUploadThreshold ? Constants.DefaultBufferSize : Constants.LargeBufferSize; // Otherwise stage individual blocks in parallel return(await UploadInParallelAsync( content, blockSize, blobHttpHeaders, metadata, conditions, progressHandler, accessTier, cancellationToken) .ConfigureAwait(false)); }
/// <summary> /// The <see cref="DeleteBlob(string, string, DeleteSnapshotsOption, BlobRequestConditions)"/> /// operation marks the specified blob or snapshot for deletion. The /// blob is later deleted during garbage collection. /// /// Note that in order to delete a blob, you must delete all of its /// snapshots. You can delete both at the same time using /// <see cref="DeleteSnapshotsOption.IncludeSnapshots"/>. /// /// For more information, see /// <see href="https://docs.microsoft.com/rest/api/storageservices/delete-blob">Delete Blob</see>. /// </summary> /// <param name="blobContainerName"> /// The name of the container containing the blob to delete. /// </param> /// <param name="blobName"> /// The name of the blob to delete. /// </param> /// <param name="snapshotsOption"> /// Specifies options for deleting blob snapshots. /// </param> /// <param name="conditions"> /// Optional <see cref="BlobRequestConditions"/> to add conditions on /// deleting this blob. /// </param> /// <returns> /// A <see cref="Response"/> on successfully deleting. The response /// cannot be used until the batch has been submitted with /// <see cref="BlobBatchClient.SubmitBatchAsync"/>. /// </returns> public virtual Response DeleteBlob( string blobContainerName, string blobName, DeleteSnapshotsOption snapshotsOption = default, BlobRequestConditions conditions = default) { var blobUri = new BlobUriBuilder(_client.Uri) { BlobContainerName = blobContainerName, BlobName = blobName }; return(DeleteBlob( blobUri.ToUri(), snapshotsOption, conditions)); }
public void StoreCreatesBlobWhenNotExist() { BlobRequestConditions uploadConditions = null; byte[] bytes = null; string contentType = null; var mock = new Mock <BlobClient>(); mock.Setup(c => c.UploadAsync( It.IsAny <Stream>(), It.IsAny <BlobHttpHeaders>(), It.IsAny <IDictionary <string, string> >(), It.IsAny <BlobRequestConditions>(), It.IsAny <IProgress <long> >(), It.IsAny <AccessTier?>(), It.IsAny <StorageTransferOptions>(), It.IsAny <CancellationToken>())) .Returns(async(Stream strm, BlobHttpHeaders headers, IDictionary <string, string> metaData, BlobRequestConditions conditions, IProgress <long> progress, AccessTier? access, StorageTransferOptions transfer, CancellationToken token) => { using var memoryStream = new MemoryStream(); strm.CopyTo(memoryStream); bytes = memoryStream.ToArray(); uploadConditions = conditions; contentType = headers?.ContentType; await Task.Yield(); var mockResponse = new Mock <Response <BlobContentInfo> >(); var blobContentInfo = BlobsModelFactory.BlobContentInfo(ETag.All, DateTimeOffset.Now.AddDays(-1), Array.Empty <byte>(), "", 1); mockResponse.Setup(c => c.Value).Returns(blobContentInfo); return(mockResponse.Object); }); var repository = new AzureBlobXmlRepository(mock.Object); repository.StoreElement(new XElement("Element"), null); Assert.AreEqual("*", uploadConditions.IfNoneMatch.ToString()); Assert.AreEqual("application/xml; charset=utf-8", contentType); var element = "<Element />"; Assert.AreEqual(bytes, GetEnvelopedContent(element)); }
protected override async Task <Stream> OpenWriteAsync( BlockBlobClient client, bool overwrite, int?bufferSize = null, BlobRequestConditions conditions = null, Dictionary <string, string> metadata = null, Dictionary <string, string> tags = null, HttpHeaderParameters httpHeaders = null, IProgress <long> progressHandler = null) => await client.OpenWriteAsync(overwrite, new BlockBlobOpenWriteOptions { BufferSize = bufferSize, OpenConditions = conditions, Metadata = metadata, Tags = tags, HttpHeaders = httpHeaders.ToBlobHttpHeaders(), ProgressHandler = progressHandler });