使用 .NET 11.x 版用戶端連結庫 Azure Blob 儲存體 程式代碼範例
本文說明使用適用於 .NET 之 Azure Blob 儲存體 客戶端連結庫 11.x 版的程式代碼範例。
在 2023 年 3 月 31 日,我們已淘汰對不符合 目前 Azure SDK 指導方針的 Azure SDK 連結庫支援。 新的 Azure SDK 連結庫會定期更新,以推動一致的體驗,並強化您的安全性狀態。 建議您轉換至新的 Azure SDK 連結庫,以利用新功能和重大安全性更新。
雖然舊版連結庫仍可在 2023 年 3 月 31 日之後使用,但不再收到 Microsoft 的官方支援和更新。 如需詳細資訊,請參閱 支援淘汰公告。
建立快照集
若要使用適用於 .NET 的 Azure 儲存體用戶端程式庫 11.x 版來建立區塊 Blob 的快照集,請使用下列其中一種方法:
下列程式碼範例說明如何使用 11.x 版建立快照集。 此範例會在建立快照集時為其指定其他中繼資料。
private static async Task CreateBlockBlobSnapshot(CloudBlobContainer container)
{
// Create a new block blob in the container.
CloudBlockBlob baseBlob = container.GetBlockBlobReference("sample-base-blob.txt");
// Add blob metadata.
baseBlob.Metadata.Add("ApproxBlobCreatedDate", DateTime.UtcNow.ToString());
try
{
// Upload the blob to create it, with its metadata.
await baseBlob.UploadTextAsync(string.Format("Base blob: {0}", baseBlob.Uri.ToString()));
// Sleep 5 seconds.
System.Threading.Thread.Sleep(5000);
// Create a snapshot of the base blob.
// You can specify metadata at the time that the snapshot is created.
// If no metadata is specified, then the blob's metadata is copied to the snapshot.
Dictionary<string, string> metadata = new Dictionary<string, string>();
metadata.Add("ApproxSnapshotCreatedDate", DateTime.UtcNow.ToString());
await baseBlob.CreateSnapshotAsync(metadata, null, null, null);
Console.WriteLine(snapshot.SnapshotQualifiedStorageUri.PrimaryUri);
}
catch (StorageException e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
throw;
}
}
刪除快照集
若要使用適用於 .NET 的 Azure 儲存體用戶端程式庫 11.x 版來刪除 Blob 及其快照集,請使用下列其中一種 Blob 刪除方法,並納入 DeleteSnapshotsOption 列舉:
下列程式碼範例說明如何在 .NET 中刪除 Blob 及其快照集,其中,blockBlob
是 [CloudBlockBlob][dotnet_CloudBlockBlob] 類型的物件:
await blockBlob.DeleteIfExistsAsync(DeleteSnapshotsOption.IncludeSnapshots, null, null, null);
建立預存的存取原則
若要在具有適用於 Azure 記憶體之 .NET 用戶端連結庫 11.x 版的容器上建立預存存取原則,請呼叫下列其中一種方法:
下列範例建立的預存存取原則只有一天的效期,且會授與讀取、寫入和列出權限:
private static async Task CreateStoredAccessPolicyAsync(CloudBlobContainer container, string policyName)
{
// Create a new stored access policy and define its constraints.
// The access policy provides create, write, read, list, and delete permissions.
SharedAccessBlobPolicy sharedPolicy = new SharedAccessBlobPolicy()
{
// When the start time for the SAS is omitted, the start time is assumed to be the time when Azure Storage receives the request.
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.List |
SharedAccessBlobPermissions.Write
};
// Get the container's existing permissions.
BlobContainerPermissions permissions = await container.GetPermissionsAsync();
// Add the new policy to the container's permissions, and set the container's permissions.
permissions.SharedAccessPolicies.Add(policyName, sharedPolicy);
await container.SetPermissionsAsync(permissions);
}
建立容器或 blob 的服務 SAS
若要建立容器的服務 SAS,請呼叫 CloudBlobContainer.GetSharedAccessSignature 方法。
private static string GetContainerSasUri(CloudBlobContainer container,
string storedPolicyName = null)
{
string sasContainerToken;
// If no stored policy is specified, create a new access policy and define its constraints.
if (storedPolicyName == null)
{
// Note that the SharedAccessBlobPolicy class is used both to define
// the parameters of an ad hoc SAS, and to construct a shared access policy
// that is saved to the container's shared access policies.
SharedAccessBlobPolicy adHocPolicy = new SharedAccessBlobPolicy()
{
// When the start time for the SAS is omitted, the start time is assumed
// to be the time when the storage service receives the request. Omitting
// the start time for a SAS that is effective immediately helps to avoid clock skew.
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.List
};
// Generate the shared access signature on the container,
// setting the constraints directly on the signature.
sasContainerToken = container.GetSharedAccessSignature(adHocPolicy, null);
Console.WriteLine("SAS for blob container (ad hoc): {0}", sasContainerToken);
Console.WriteLine();
}
else
{
// Generate the shared access signature on the container. In this case,
// all of the constraints for the shared access signature are specified
// on the stored access policy, which is provided by name. It is also possible
// to specify some constraints on an ad hoc SAS and others on the stored access policy.
sasContainerToken = container.GetSharedAccessSignature(null, storedPolicyName);
Console.WriteLine("SAS for container (stored access policy): {0}", sasContainerToken);
Console.WriteLine();
}
// Return the URI string for the container, including the SAS token.
return container.Uri + sasContainerToken;
}
建立 blob 的服務 SAS
若要建立 blob 的服務 SAS,請呼叫 CloudBlob.GetSharedAccessSignature 方法。
private static string GetBlobSasUri(CloudBlobContainer container,
string blobName,
string policyName = null)
{
string sasBlobToken;
// Get a reference to a blob within the container.
// Note that the blob may not exist yet, but a SAS can still be created for it.
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
if (policyName == null)
{
// Create a new access policy and define its constraints.
// Note that the SharedAccessBlobPolicy class is used both to define the parameters
// of an ad hoc SAS, and to construct a shared access policy that is saved to
// the container's shared access policies.
SharedAccessBlobPolicy adHocSAS = new SharedAccessBlobPolicy()
{
// When the start time for the SAS is omitted, the start time is assumed to be
// the time when the storage service receives the request. Omitting the start time
// for a SAS that is effective immediately helps to avoid clock skew.
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessBlobPermissions.Read |
SharedAccessBlobPermissions.Write |
SharedAccessBlobPermissions.Create
};
// Generate the shared access signature on the blob,
// setting the constraints directly on the signature.
sasBlobToken = blob.GetSharedAccessSignature(adHocSAS);
Console.WriteLine("SAS for blob (ad hoc): {0}", sasBlobToken);
Console.WriteLine();
}
else
{
// Generate the shared access signature on the blob. In this case, all of the constraints
// for the SAS are specified on the container's stored access policy.
sasBlobToken = blob.GetSharedAccessSignature(null, policyName);
Console.WriteLine("SAS for blob (stored access policy): {0}", sasBlobToken);
Console.WriteLine();
}
// Return the URI string for the container, including the SAS token.
return blob.Uri + sasBlobToken;
}
建立帳戶 SAS
若要建立容器的帳戶 SAS,請呼叫 CloudStorageAccount.GetSharedAccessSignature 方法。
下列程式碼範例會建立適用於 Blob 和檔案服務的帳戶 SAS,並提供用戶端權限讀取、寫入和列出權限來存取服務層級 API。 帳戶 SAS 會將通訊協定限制為 HTTPS,因此必須使用 HTTPS 提出要求。 請記得以您自己的值取代角括號中的預留位置值:
static string GetAccountSASToken()
{
// To create the account SAS, you need to use Shared Key credentials. Modify for your account.
const string ConnectionString = "DefaultEndpointsProtocol=https;AccountName=<storage-account>;AccountKey=<account-key>";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
// Create a new access policy for the account.
SharedAccessAccountPolicy policy = new SharedAccessAccountPolicy()
{
Permissions = SharedAccessAccountPermissions.Read |
SharedAccessAccountPermissions.Write |
SharedAccessAccountPermissions.List,
Services = SharedAccessAccountServices.Blob | SharedAccessAccountServices.File,
ResourceTypes = SharedAccessAccountResourceTypes.Service,
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Protocols = SharedAccessProtocol.HttpsOnly
};
// Return the SAS token.
return storageAccount.GetSharedAccessSignature(policy);
}
從用戶端使用帳戶 SAS
在此程式碼片段中,將 <storage-account>
預留位置取代為您的儲存體帳戶名稱。
static void UseAccountSAS(string sasToken)
{
// Create new storage credentials using the SAS token.
StorageCredentials accountSAS = new StorageCredentials(sasToken);
// Use these credentials and the account name to create a Blob service client.
CloudStorageAccount accountWithSAS = new CloudStorageAccount(accountSAS, "<storage-account>", endpointSuffix: null, useHttps: true);
CloudBlobClient blobClientWithSAS = accountWithSAS.CreateCloudBlobClient();
// Now set the service properties for the Blob client created with the SAS.
blobClientWithSAS.SetServiceProperties(new ServiceProperties()
{
HourMetrics = new MetricsProperties()
{
MetricsLevel = MetricsLevel.ServiceAndApi,
RetentionDays = 7,
Version = "1.0"
},
MinuteMetrics = new MetricsProperties()
{
MetricsLevel = MetricsLevel.ServiceAndApi,
RetentionDays = 7,
Version = "1.0"
},
Logging = new LoggingProperties()
{
LoggingOperations = LoggingOperations.All,
RetentionDays = 14,
Version = "1.0"
}
});
// The permissions granted by the account SAS also permit you to retrieve service properties.
ServiceProperties serviceProperties = blobClientWithSAS.GetServiceProperties();
Console.WriteLine(serviceProperties.HourMetrics.MetricsLevel);
Console.WriteLine(serviceProperties.HourMetrics.RetentionDays);
Console.WriteLine(serviceProperties.HourMetrics.Version);
}
Blob 的開放式並行存取
程式碼範例:
public void DemonstrateOptimisticConcurrencyBlob(string containerName, string blobName)
{
Console.WriteLine("Demonstrate optimistic concurrency");
// Parse connection string and create container.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
container.CreateIfNotExists();
// Create test blob. The default strategy is last writer wins, so
// write operation will overwrite existing blob if present.
CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobName);
blockBlob.UploadText("Hello World!");
// Retrieve the ETag from the newly created blob.
string originalETag = blockBlob.Properties.ETag;
Console.WriteLine("Blob added. Original ETag = {0}", originalETag);
/// This code simulates an update by another client.
string helloText = "Blob updated by another client.";
// No ETag was provided, so original blob is overwritten and ETag updated.
blockBlob.UploadText(helloText);
Console.WriteLine("Blob updated. Updated ETag = {0}", blockBlob.Properties.ETag);
// Now try to update the blob using the original ETag value.
try
{
Console.WriteLine(@"Attempt to update blob using original ETag
to generate if-match access condition");
blockBlob.UploadText(helloText, accessCondition: AccessCondition.GenerateIfMatchCondition(originalETag));
}
catch (StorageException ex)
{
if (ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.PreconditionFailed)
{
Console.WriteLine(@"Precondition failure as expected.
Blob's ETag does not match.");
}
else
{
throw;
}
}
Console.WriteLine();
}
Blob 的封閉式並行存取
程式碼範例:
public void DemonstratePessimisticConcurrencyBlob(string containerName, string blobName)
{
Console.WriteLine("Demonstrate pessimistic concurrency");
// Parse connection string and create container.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
container.CreateIfNotExists();
CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobName);
blockBlob.UploadText("Hello World!");
Console.WriteLine("Blob added.");
// Acquire lease for 15 seconds.
string lease = blockBlob.AcquireLease(TimeSpan.FromSeconds(15), null);
Console.WriteLine("Blob lease acquired. Lease = {0}", lease);
// Update blob using lease. This operation should succeed.
const string helloText = "Blob updated";
var accessCondition = AccessCondition.GenerateLeaseCondition(lease);
blockBlob.UploadText(helloText, accessCondition: accessCondition);
Console.WriteLine("Blob updated using an exclusive lease");
// Simulate another client attempting to update to blob without providing lease.
try
{
// Operation will fail as no valid lease was provided.
Console.WriteLine("Now try to update blob without valid lease.");
blockBlob.UploadText("Update operation will fail without lease.");
}
catch (StorageException ex)
{
if (ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.PreconditionFailed)
{
Console.WriteLine(@"Precondition failure error as expected.
Blob lease not provided.");
}
else
{
throw;
}
}
// Release lease proactively.
blockBlob.ReleaseLease(accessCondition);
Console.WriteLine();
}
使用 Blob 記憶體建置高可用性應用程式
下載 範例專案、解壓縮 (解壓縮) storage-dotnet-circuit-breaker-pattern-ha-apps-using-ra-grs.zip 檔案,然後流覽至 v11 資料夾以尋找項目檔。
您也可以使用 git 將應用程式的複本下載到您的開發環境。 v11 資料夾中的範例專案包含主控台應用程式。
git clone https://github.com/Azure-Samples/storage-dotnet-circuit-breaker-pattern-ha-apps-using-ra-grs.git
設定範例
在應用程式,您必須提供儲存體帳戶的連接字串。 您可以在執行應用程式的本機電腦上,將此連接字串儲存在環境變數內。 請根據您的作業系統,遵循以下其中一個範例來建立環境變數。
在 Azure 入口網站中,瀏覽至您的儲存體帳戶。 在儲存體帳戶中選取 [設定] 下的 [存取金鑰]。 從主要或次要金鑰複製連接字串。 根據您的作業系統執行下列其中一個命令,將 <yourconnectionstring> 取代為實際的連接字串。 此命令會將一個環境變數儲存至本機電腦。 在 Windows 中,必須重新載入命令提示字元或您所使用的殼層,才能使用此環境變數。
執行主控台應用程式
在 Visual Studio 中,按下 F5 或選取 [啟動],開始對應用程式進行偵錯。 若已設定套件還原,Visual Studio 會自動還原缺少的 NuGet 套件,如需深入了解,請造訪透過套件還原來安裝和解除安裝套件。
隨即會有主控台視窗啟動,應用程式也會開始執行。 此應用程式會將 HelloWorld.png 影像從解決方案上傳到儲存體帳戶。 此應用程式會進行檢查,以確定影像已複寫至次要 RA-GZRS 端點。 之後,則會開始下載影像,最多會下載 999 次。 每次的讀取都會以 P 或 S 來表示。其中,P 代表主要端點,S 則代表次要端點。
在程式碼範例中,系統會使用 Program.cs
檔案中的 RunCircuitBreakerAsync
工作,透過 DownloadToFileAsync 方法從儲存體帳戶下載影像。 在下載之前,系統會先定義 OperationContext。 作業內容會定義事件處理常式,當下載作業成功完成,或下載作業失敗而正在重試時,便會引發這些處理常式。
了解範例程式碼
重試事件處理常式
當影像下載失敗,並設定為重試時,便會呼叫 OperationContextRetrying
事件處理常式。 如果達到應用程式中定義的重試次數上限,該項要求的 LocationMode 就會變更為 SecondaryOnly
。 這項設定會迫使應用程式嘗試從次要端點下載影像。 因為不會無限期地重試主要端點,這項設定可減少要求該影像所花費的時間。
private static void OperationContextRetrying(object sender, RequestEventArgs e)
{
retryCount++;
Console.WriteLine("Retrying event because of failure reading the primary. RetryCount = " + retryCount);
// Check if we have had more than n retries in which case switch to secondary.
if (retryCount >= retryThreshold)
{
// Check to see if we can fail over to secondary.
if (blobClient.DefaultRequestOptions.LocationMode != LocationMode.SecondaryOnly)
{
blobClient.DefaultRequestOptions.LocationMode = LocationMode.SecondaryOnly;
retryCount = 0;
}
else
{
throw new ApplicationException("Both primary and secondary are unreachable. Check your application's network connection. ");
}
}
}
要求已完成的事件處理常式
當影像下載成功時,便會呼叫 OperationContextRequestCompleted
事件處理常式。 如果應用程式使用次要端點,則應用程式會繼續使用此端點,但最多 20 次。 20 次後,應用程式就會將 LocationMode 重設為 PrimaryThenSecondary
,並重試主要端點。 如果要求成功,應用程式會繼續從主要端點讀取。
private static void OperationContextRequestCompleted(object sender, RequestEventArgs e)
{
if (blobClient.DefaultRequestOptions.LocationMode == LocationMode.SecondaryOnly)
{
// You're reading the secondary. Let it read the secondary [secondaryThreshold] times,
// then switch back to the primary and see if it's available now.
secondaryReadCount++;
if (secondaryReadCount >= secondaryThreshold)
{
blobClient.DefaultRequestOptions.LocationMode = LocationMode.PrimaryThenSecondary;
secondaryReadCount = 0;
}
}
}
將大量隨機數據上傳至 Azure 記憶體
執行緒的最小和最大數目會設定為 100,以確保能允許大量的並行連線。
private static async Task UploadFilesAsync()
{
// Create five randomly named containers to store the uploaded files.
CloudBlobContainer[] containers = await GetRandomContainersAsync();
var currentdir = System.IO.Directory.GetCurrentDirectory();
// Path to the directory to upload
string uploadPath = currentdir + "\\upload";
// Start a timer to measure how long it takes to upload all the files.
Stopwatch time = Stopwatch.StartNew();
try
{
Console.WriteLine("Iterating in directory: {0}", uploadPath);
int count = 0;
int max_outstanding = 100;
int completed_count = 0;
// Define the BlobRequestOptions on the upload.
// This includes defining an exponential retry policy to ensure that failed connections
// are retried with a back off policy. As multiple large files are being uploaded using
// large block sizes, this can cause an issue if an exponential retry policy is not defined.
// Additionally, parallel operations are enabled with a thread count of 8.
// This should be a multiple of the number of processor cores in the machine.
// Lastly, MD5 hash validation is disabled for this example, improving the upload speed.
BlobRequestOptions options = new BlobRequestOptions
{
ParallelOperationThreadCount = 8,
DisableContentMD5Validation = true,
StoreBlobContentMD5 = false
};
// Create a new instance of the SemaphoreSlim class to
// define the number of threads to use in the application.
SemaphoreSlim sem = new SemaphoreSlim(max_outstanding, max_outstanding);
List<Task> tasks = new List<Task>();
Console.WriteLine("Found {0} file(s)", Directory.GetFiles(uploadPath).Count());
// Iterate through the files
foreach (string path in Directory.GetFiles(uploadPath))
{
var container = containers[count % 5];
string fileName = Path.GetFileName(path);
Console.WriteLine("Uploading {0} to container {1}", path, container.Name);
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
// Set the block size to 100MB.
blockBlob.StreamWriteSizeInBytes = 100 * 1024 * 1024;
await sem.WaitAsync();
// Create a task for each file to upload. The tasks are
// added to a collection and all run asynchronously.
tasks.Add(blockBlob.UploadFromFileAsync(path, null, options, null).ContinueWith((t) =>
{
sem.Release();
Interlocked.Increment(ref completed_count);
}));
count++;
}
// Run all the tasks asynchronously.
await Task.WhenAll(tasks);
time.Stop();
Console.WriteLine("Upload has been completed in {0} seconds. Press any key to continue", time.Elapsed.TotalSeconds.ToString());
Console.ReadLine();
}
catch (DirectoryNotFoundException ex)
{
Console.WriteLine("Error parsing files in the directory: {0}", ex.Message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
除了設定執行緒和連線限制設定,UploadFromStreamAsync 的 BlobRequestOptions 方法也會設定為使用平行處理原則,並停用 MD5 雜湊驗證。 檔案會以 100 MB 的區塊上傳,這項設定可提供更佳的效能,但如果使用效能差的網路則可能提高成本,因為整個 100 MB 的區塊可能會因為失敗而需要重試。
屬性 | 值 | 描述 |
---|---|---|
ParallelOperationThreadCount | 8 | 上傳時,此設定會將 Blob 分成區塊。 為達到最高效能,此值應為核心數目的 8 倍。 |
DisableContentMD5Validation | true | 此屬性可停用檢查上傳內容的 MD5 雜湊。 停用 MD5 驗證可獲得較快的傳輸速度。 但不會確認所傳輸檔案的有效性和完整性。 |
StoreBlobContentMD5 | false | 此屬性可判斷是否已計算及儲存檔案的 MD5 雜湊。 |
RetryPolicy | 具有 2 秒的輪詢,最多重試 10 次 | 決定要求的重試原則。 連線失敗時進行重試,在此範例中,ExponentialRetry 原則設定為具有 2 秒的輪詢,以及最多重試 10 次。 當您的應用程式快達到 Blob 儲存體的延展性目標時,此設定就十分重要。 如需詳細資訊,請參閱 Blob 儲存體的延展性和效能目標。 |
從 Azure 儲存體下載大量隨機資料
應用程式會讀取 storageconnectionstring中指定之儲存體帳戶內的容器。 其會使用容器中的 ListBlobsSegmented 方法逐次查看 10 個 Blob,並使用 ListBlobsSegmentedAsync 方法將 Blob 下載到本機電腦。
下表顯示下載每個 Blob 時所定義的 BlobRequestOptions。
屬性 | 值 | 描述 |
---|---|---|
DisableContentMD5Validation | true | 此屬性可停用檢查上傳內容的 MD5 雜湊。 停用 MD5 驗證可獲得較快的傳輸速度。 但不會確認所傳輸檔案的有效性和完整性。 |
StoreBlobContentMD5 | false | 此屬性可判斷是否已計算及儲存 MD5 雜湊。 |
private static async Task DownloadFilesAsync()
{
CloudBlobClient blobClient = GetCloudBlobClient();
// Define the BlobRequestOptions on the download, including disabling MD5
// hash validation for this example, this improves the download speed.
BlobRequestOptions options = new BlobRequestOptions
{
DisableContentMD5Validation = true,
StoreBlobContentMD5 = false
};
// Retrieve the list of containers in the storage account.
// Create a directory and configure variables for use later.
BlobContinuationToken continuationToken = null;
List<CloudBlobContainer> containers = new List<CloudBlobContainer>();
do
{
var listingResult = await blobClient.ListContainersSegmentedAsync(continuationToken);
continuationToken = listingResult.ContinuationToken;
containers.AddRange(listingResult.Results);
}
while (continuationToken != null);
var directory = Directory.CreateDirectory("download");
BlobResultSegment resultSegment = null;
Stopwatch time = Stopwatch.StartNew();
// Download the blobs
try
{
List<Task> tasks = new List<Task>();
int max_outstanding = 100;
int completed_count = 0;
// Create a new instance of the SemaphoreSlim class to
// define the number of threads to use in the application.
SemaphoreSlim sem = new SemaphoreSlim(max_outstanding, max_outstanding);
// Iterate through the containers
foreach (CloudBlobContainer container in containers)
{
do
{
// Return the blobs from the container, 10 at a time.
resultSegment = await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, 10, continuationToken, null, null);
continuationToken = resultSegment.ContinuationToken;
{
foreach (var blobItem in resultSegment.Results)
{
if (((CloudBlob)blobItem).Properties.BlobType == BlobType.BlockBlob)
{
// Get the blob and add a task to download the blob asynchronously from the storage account.
CloudBlockBlob blockBlob = container.GetBlockBlobReference(((CloudBlockBlob)blobItem).Name);
Console.WriteLine("Downloading {0} from container {1}", blockBlob.Name, container.Name);
await sem.WaitAsync();
tasks.Add(blockBlob.DownloadToFileAsync(directory.FullName + "\\" + blockBlob.Name, FileMode.Create, null, options, null).ContinueWith((t) =>
{
sem.Release();
Interlocked.Increment(ref completed_count);
}));
}
}
}
}
while (continuationToken != null);
}
// Creates an asynchronous task that completes when all the downloads complete.
await Task.WhenAll(tasks);
}
catch (Exception e)
{
Console.WriteLine("\nError encountered during transfer: {0}", e.Message);
}
time.Stop();
Console.WriteLine("Download has been completed in {0} seconds. Press any key to continue", time.Elapsed.TotalSeconds.ToString());
Console.ReadLine();
}
(傳統) 啟用 Azure 儲存體分析 記錄
程式碼範例:
var storageAccount = CloudStorageAccount.Parse(connStr);
var queueClient = storageAccount.CreateCloudQueueClient();
var serviceProperties = queueClient.GetServiceProperties();
serviceProperties.Logging.LoggingOperations = LoggingOperations.All;
serviceProperties.Logging.RetentionDays = 2;
queueClient.SetServiceProperties(serviceProperties);
修改記錄資料保留期間
下列範例會將 Blob 和佇列儲存體服務的保留期間列印到主控台。
var storageAccount = CloudStorageAccount.Parse(connectionString);
var blobClient = storageAccount.CreateCloudBlobClient();
var queueClient = storageAccount.CreateCloudQueueClient();
var blobserviceProperties = blobClient.GetServiceProperties();
var queueserviceProperties = queueClient.GetServiceProperties();
Console.WriteLine("Retention period for logs from the blob service is: " +
blobserviceProperties.Logging.RetentionDays.ToString());
Console.WriteLine("Retention period for logs from the queue service is: " +
queueserviceProperties.Logging.RetentionDays.ToString());
下列範例會將 Blob 和佇列儲存體服務記錄的保留期限變更為 4 天。
blobserviceProperties.Logging.RetentionDays = 4;
queueserviceProperties.Logging.RetentionDays = 4;
blobClient.SetServiceProperties(blobserviceProperties);
queueClient.SetServiceProperties(queueserviceProperties);
(傳統) 啟用 Azure 儲存體分析 計量
程式碼範例:
var storageAccount = CloudStorageAccount.Parse(connStr);
var queueClient = storageAccount.CreateCloudQueueClient();
var serviceProperties = queueClient.GetServiceProperties();
serviceProperties.HourMetrics.MetricsLevel = MetricsLevel.Service;
serviceProperties.HourMetrics.RetentionDays = 10;
queueClient.SetServiceProperties(serviceProperties);
針對用戶端應用程式設定傳輸層安全性 (TLS)
下列範例示範如何使用 Azure 記憶體用戶端連結庫 11.x 版在 .NET 用戶端中啟用 TLS 1.2:
static void EnableTls12()
{
// Enable TLS 1.2 before connecting to Azure Storage
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
// Add your connection string here.
string connectionString = "";
// Connect to Azure Storage and create a new container.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("sample-container");
container.CreateIfNotExists();
}
監視、診斷與疑難排解 Microsoft Azure 儲存體 (傳統)
如果儲存體用戶端程式庫在用戶端擲回 StorageException,則 RequestInformation 屬性所包含的 RequestResult 物件裡會出現 ServiceRequestID 屬性。 您可以從 OperationContext 執行個體存取 RequestResult 物件。
下列程式碼範例示範如何藉由附加 OperationContext 物件要求至儲存體服務來設定自訂的 ClientRequestId 值。 此範例同時示範如何從回應訊息擷取 ServerRequestId 值。
//Parse the connection string for the storage account.
const string ConnectionString = "DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Create an Operation Context that includes custom ClientRequestId string based on constants defined within the application along with a Guid.
OperationContext oc = new OperationContext();
oc.ClientRequestID = String.Format("{0} {1} {2} {3}", HOSTNAME, APPNAME, USERID, Guid.NewGuid().ToString());
try
{
CloudBlobContainer container = blobClient.GetContainerReference("democontainer");
ICloudBlob blob = container.GetBlobReferenceFromServer("testImage.jpg", null, null, oc);
var downloadToPath = string.Format("./{0}", blob.Name);
using (var fs = File.OpenWrite(downloadToPath))
{
blob.DownloadToStream(fs, null, null, oc);
Console.WriteLine("\t Blob downloaded to file: {0}", downloadToPath);
}
}
catch (StorageException storageException)
{
Console.WriteLine("Storage exception {0} occurred", storageException.Message);
// Multiple results may exist due to client side retry logic - each retried operation will have a unique ServiceRequestId
foreach (var result in oc.RequestResults)
{
Console.WriteLine("HttpStatus: {0}, ServiceRequestId {1}", result.HttpStatusCode, result.ServiceRequestID);
}
}
調查用戶端效能問題 - 停用 Nagle 演算法
程式碼範例:
var storageAccount = CloudStorageAccount.Parse(connStr);
ServicePoint queueServicePoint = ServicePointManager.FindServicePoint(storageAccount.QueueEndpoint);
queueServicePoint.UseNagleAlgorithm = false;
調查網路等待時間問題 - 設定跨原始來源資源分享 (CORS)
程式碼範例:
CloudBlobClient client = new CloudBlobClient(blobEndpoint, new StorageCredentials(accountName, accountKey));
// Set the service properties.
ServiceProperties sp = client.GetServiceProperties();
sp.DefaultServiceVersion = "2013-08-15";
CorsRule cr = new CorsRule();
cr.AllowedHeaders.Add("*");
cr.AllowedMethods = CorsHttpMethods.Get | CorsHttpMethods.Put;
cr.AllowedOrigins.Add("http://www.contoso.com");
cr.ExposedHeaders.Add("x-ms-*");
cr.MaxAgeInSeconds = 5;
sp.Cors.CorsRules.Clear();
sp.Cors.CorsRules.Add(cr);
client.SetServiceProperties(sp);
建立指定大小的空分頁 Blob
若要建立分頁 Blob,首先需建立 CloudBlobClient 物件,搭配用來存取您儲存體帳戶 (圖 1 中的 pbaccount) 之 Blob 儲存體的基底 URI,以及 StorageCredentialsAccountAndKey 物件,如下列範例所示。 然後,此範例會建立 CloudBlobContainer 物件的參照,然後建立容器 (testvhds) (如果它尚未存在)。 然後,透過 CloudBlobContainer 物件,建立 CloudPageBlob 物件的參照,方法是指定要存取的分頁 Blob 名稱 (os4.vhd)。 若要建立分頁 Blob,請呼叫 CloudPageBlob.Create 傳入要建立之 Blob 的大小上限。 blobSize 必須是 512 位元組的倍數。
using Microsoft.Azure;
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;
long OneGigabyteAsBytes = 1024 * 1024 * 1024;
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference("testvhds");
// Create the container if it doesn't already exist.
container.CreateIfNotExists();
CloudPageBlob pageBlob = container.GetPageBlobReference("os4.vhd");
pageBlob.Create(16 * OneGigabyteAsBytes);
調整分頁 Blob 大小
若要在建立之後重新調整分頁 Blob 的大小,請使用調整大小方法。 要求的大小應該是 512 位元組的倍數。
pageBlob.Resize(32 * OneGigabyteAsBytes);
將分頁寫入分頁 Blob
若要寫入分頁,請使用 CloudPageBlob.WritePages 方法。
pageBlob.WritePages(dataStream, startingOffset);
從分頁 Blob 讀取分頁
若要讀取分頁,請使用 CloudPageBlob.DownloadRangeToByteArray 方法,從分頁 Blob 讀取位元組範圍。
byte[] buffer = new byte[rangeSize];
pageBlob.DownloadRangeToByteArray(buffer, bufferOffset, pageBlobOffset, rangeSize);
若要判斷有哪些分頁是由資料所支援,請使用 CloudPageBlob.GetPageRanges。 然後,您可以對傳回的範圍進行列舉,並下載每個範圍中的資料。
IEnumerable<PageRange> pageRanges = pageBlob.GetPageRanges();
foreach (PageRange range in pageRanges)
{
// Calculate the range size
int rangeSize = (int)(range.EndOffset + 1 - range.StartOffset);
byte[] buffer = new byte[rangeSize];
// Read from the correct starting offset in the page blob and
// place the data in the bufferOffset of the buffer byte array
pageBlob.DownloadRangeToByteArray(buffer, bufferOffset, range.StartOffset, rangeSize);
// Then use the buffer for the page range just read
}