05/10/2021
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Azure; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using Azure.Storage.Sas; using Microsoft.Extensions.Logging; namespace Storage { internal sealed class BlobContainerClient1 : Azure.Storage.Blobs.BlobContainerClient { private readonly string _connectionString; private readonly string _blobContainerName; private const char SEPARATOR = '/'; private readonly string _rootDirectory; private readonly ILogger _logger; private bool _initialized; private readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1); public BlobContainerClient1( ILogger logger, string connectionString, string blobContainerName, string rootDirectory = null, BlobClientOptions options = null) : base(connectionString, blobContainerName, options) { _initialized = false; _rootDirectory = GetRootDirectoryName(rootDirectory); _connectionString = connectionString; _blobContainerName = blobContainerName; _logger = logger; } public async Task WriteFileAsync( string directory, string name, Stream content, CancellationToken cancellationToken) { string path = GetFilePath(directory, name); _logger.LogDebug($"{_blobContainerName}: Writing contents of '{path}'..."); var client = await GetBlobClientAsync(directory, name); await client.UploadAsync(content, true, cancellationToken); _logger.LogDebug($"{_blobContainerName}: Content of '{path}' written."); } public async Task UploadAsync( string directory, string name, Stream content, CancellationToken cancellationToken) { await WriteFileAsync(directory, name, content, cancellationToken); } public async Task ReadFileAsStringAsync( string directory, string name, CancellationToken cancellationToken) { var client = await GetBlobClientAsync(directory, name); using (BlobDownloadInfo download = await client.DownloadAsync(cancellationToken)) { StreamReader reader = new StreamReader(download.Content); return await reader.ReadToEndAsync(); } } public async Task DownloadAsync( string directory, string name, CancellationToken cancellationToken) { return await ReadFileAsStringAsync(directory, name, cancellationToken); } public async Task ReadFileAsStringIfExistsAsync( string directory, string name, CancellationToken cancellationToken) { try { return await ReadFileAsStringAsync(directory, name, cancellationToken); } catch (RequestFailedException ex) when (ex.ErrorCode == BlobErrorCode.BlobNotFound) { return null; } } public async Task GetUriAsync( string directory, string name, FileAccessPermission permission, TimeSpan validTill) { return await GetBlobUriAsync(directory, name, permission, validTill); } public async Task ExistsFileAsync( string directory, string name, CancellationToken cancellationToken) { var client = await GetBlobClientAsync(directory, name); return await client.ExistsAsync(cancellationToken); } public async Task ExistsAsync( string directory, string name, CancellationToken cancellationToken) { return await ExistsFileAsync(directory, name, cancellationToken); } public async Task ReadFileAsync(string directory, string name, CancellationToken cancellationToken) { var client = await GetBlobClientAsync(directory, name); return await client.OpenReadAsync(cancellationToken: cancellationToken); } public async Task OpenReadAsync( string directory, string name, CancellationToken cancellationToken) { return await ReadFileAsync(directory, name, cancellationToken); } public async Task DeleteDirectoryAsync( string directory, Func namePredicate, CancellationToken cancellationToken) { _logger.LogDebug($"{_blobContainerName}: Directory '{directory}' deleting..."); await EnumerateForDeleteAsync(directory, async (blob, token) => { if (!namePredicate(blob.Name)) return; await DeleteBlobAsync(blob, token); }, cancellationToken); _logger.LogDebug($"{_blobContainerName}: Directory '{directory}' deleted."); } public async Task DeleteDirectoryAsync( string directory, CancellationToken cancellationToken) { _logger.LogDebug($"{_blobContainerName}: Directory '{directory}' deleting..."); await EnumerateForDeleteAsync(directory, DeleteBlobAsync, cancellationToken); _logger.LogDebug($"{_blobContainerName}: Directory '{directory}' deleted."); } public async Task DeleteBlobAsync( string directory, string name, CancellationToken cancellationToken) { var client = await GetBlobClientAsync(directory, name); await client.DeleteIfExistsAsync(cancellationToken: cancellationToken); } public async Task GetPropertiesAsync( string directory, string name, CancellationToken cancellationToken) { var client = await GetBlobClientAsync(directory, name); return await client.GetPropertiesAsync(cancellationToken: cancellationToken); } public async Task GetMetaDataAsync( string directory, string name, CancellationToken cancellationToken) { return await GetPropertiesAsync(directory, name, cancellationToken); } public async Task UpdateMetadataAsync( string directory, string name, IDictionary metadata, CancellationToken cancellationToken) { var client = await GetBlobClientAsync(directory, name); await client.SetMetadataAsync(metadata, cancellationToken: cancellationToken); } Private Method private async Task DeleteBlobAsync( BlobItem blob, CancellationToken cancellationToken) { try { await DeleteBlobIfExistsAsync(blob.Name, cancellationToken: cancellationToken); } catch (Exception ex) { _logger.LogWarning($"Failed to delete blob {blob.Name}, reason: {ex.Message}."); } } private async Task GetBlobUriAsync( string directory, string name, FileAccessPermission permission, TimeSpan validTill) { var client = await GetBlobClientAsync(directory, name); var permissions = GetBlobSasPermissions(permission); return client.GenerateSasUri(permissions, DateTimeOffset.UtcNow.Add(validTill)); } private async Task CreateBlobClientAsync( string blobName, BlobClientOptions options = null) { await EnsureInitializedAsync(); return new BlobClient(_connectionString, _blobContainerName, blobName, options); } private async Task GetBlobClientAsync( string directory, string name) { string path = GetFilePath(directory, name); return await CreateBlobClientAsync(path); } private async Task EnumerateForDeleteAsync( string directoryName, Func blobAction, CancellationToken cancellationToken) { string prefixBlobName = GetDirectoryName(directoryName); List blobItems = new List(); await GetBlobsHierarchicalAsyn(blobItems, this, prefixBlobName, 200, cancellationToken); var blobTasks = blobItems.OfType().Select(x => blobAction(x, cancellationToken)); await Task.WhenAll(blobTasks); } private string GetDirectoryName(string name) { return NormalizeName($"{_rootDirectory}{name}"); } private string GetRootDirectoryName(string name) { if (string.IsNullOrEmpty(name)) return ""; if (!name.EndsWith(SEPARATOR.ToString())) name += SEPARATOR; return NormalizeName(name); } private string NormalizeName(string name) { return string.Join(SEPARATOR.ToString(), name.Split(SEPARATOR).Select(Uri.EscapeDataString)); } private string GetFilePath(string directory, string name) { var path = GetDirectoryName(directory); if (!string.IsNullOrEmpty(path)) path += SEPARATOR; path = path.Replace($"{SEPARATOR}{SEPARATOR}", SEPARATOR.ToString()); path += NormalizeName(name); return path; } private async Task GetBlobsHierarchicalAsyn( List blobItems, BlobContainerClient container, string prefix, int?...
https://quangphamsoft.wordpress.com/2021/01/05/blob-v12-client/
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Azure; using Azure.Storage.Blobs; using Azure.Storage…