Blob Storage -- основное хранилище неструктурированных данных в Azure. На экзамене AZ-204 проверяют знание SDK, SAS-токенов и lifecycle management.
Работа с Blob Storage в C#
Подключение через SDK
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Identity;
// Рекомендуемый способ -- через DefaultAzureCredential (без ключей!)
var blobServiceClient = new BlobServiceClient(
new Uri("https://mystorageaccount.blob.core.windows.net"),
new DefaultAzureCredential());
// Альтернатива: connection string (для dev/test)
var blobServiceClient = new BlobServiceClient(connectionString);
// Получение контейнера
var containerClient = blobServiceClient.GetBlobContainerClient("orders");
// Создание контейнера (если не существует)
await containerClient.CreateIfNotExistsAsync(PublicAccessType.None);
CRUD-операции
// Upload: загрузка файла
var blobClient = containerClient.GetBlobClient("order-123.json");
await blobClient.UploadAsync(stream, new BlobHttpHeaders
{
ContentType = "application/json"
});
// Upload из строки
var data = BinaryData.FromString(JsonSerializer.Serialize(order));
await blobClient.UploadAsync(data, overwrite: true);
// Download: скачивание файла
BlobDownloadInfo download = await blobClient.DownloadAsync();
using var reader = new StreamReader(download.Content);
string content = await reader.ReadToEndAsync();
// List: листинг блобов
await foreach (var blob in containerClient.GetBlobsAsync())
{
Console.WriteLine($"{blob.Name} - {blob.Properties.ContentLength} bytes");
}
// Delete: удаление
await blobClient.DeleteIfExistsAsync(DeleteSnapshotsOption.IncludeSnapshots);
Метаданные и свойства
// Установка метаданных
var metadata = new Dictionary<string, string>
{
{ "orderId", "123" },
{ "customerId", "cust-001" }
};
await blobClient.SetMetadataAsync(metadata);
// Чтение свойств
var properties = await blobClient.GetPropertiesAsync();
Console.WriteLine($"Size: {properties.Value.ContentLength}");
Console.WriteLine($"Tier: {properties.Value.AccessTier}");
Lifecycle Management
Автоматическое перемещение блобов между уровнями доступа и удаление старых данных:
{
"rules": [
{
"name": "move-to-cool-and-archive",
"type": "Lifecycle",
"definition": {
"actions": {
"baseBlob": {
"tierToCool": { "daysAfterModificationGreaterThan": 30 },
"tierToArchive": { "daysAfterModificationGreaterThan": 90 },
"delete": { "daysAfterModificationGreaterThan": 365 }
},
"snapshot": {
"delete": { "daysAfterCreationGreaterThan": 90 }
}
},
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["orders/", "reports/"]
}
}
}
]
}
Политика выше делает следующее:
- Через 30 дней: перемещает блобы из Hot в Cool
- Через 90 дней: перемещает из Cool в Archive
- Через 365 дней: удаляет блоб
- Снимки (snapshots) удаляются через 90 дней
- Действует только на блобы с префиксом "orders/" и "reports/"
SAS Tokens (Shared Access Signature)
SAS-токен предоставляет временный ограниченный доступ к ресурсам хранилища без раскрытия ключа аккаунта.
Типы SAS
| Тип | Область | Описание |
|---|---|---|
| Service SAS | Один сервис (Blob/Queue/Table/File) | Доступ к конкретному контейнеру или блобу |
| Account SAS | Весь Storage Account | Доступ к нескольким сервисам |
| User Delegation SAS | Blob и Data Lake | Подписан учетными данными Entra ID (рекомендуется!) |
Генерация SAS в C#
// Service SAS
var sasBuilder = new BlobSasBuilder
{
BlobContainerName = "orders",
BlobName = "order-123.json",
Resource = "b", // "b" = blob, "c" = container
ExpiresOn = DateTimeOffset.UtcNow.AddHours(1)
};
sasBuilder.SetPermissions(BlobSasPermissions.Read);
var sasUri = blobClient.GenerateSasUri(sasBuilder);
// Результат: https://...blob.core.windows.net/orders/order-123.json?sv=...&sig=...
User Delegation SAS (рекомендуемый)
// User Delegation SAS -- подписан через Entra ID, без ключа аккаунта
var userDelegationKey = await blobServiceClient.GetUserDelegationKeyAsync(
DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow.AddHours(1));
var sasBuilder = new BlobSasBuilder
{
BlobContainerName = "orders",
BlobName = "order-123.json",
Resource = "b",
ExpiresOn = DateTimeOffset.UtcNow.AddHours(1)
};
sasBuilder.SetPermissions(BlobSasPermissions.Read);
var blobUriBuilder = new BlobUriBuilder(blobClient.Uri)
{
Sas = sasBuilder.ToSasQueryParameters(userDelegationKey, blobServiceClient.AccountName)
};
var sasUri = blobUriBuilder.ToUri();
Stored Access Policy
Stored Access Policy позволяет управлять несколькими SAS-токенами. Если нужно отозвать доступ, достаточно изменить или удалить политику -- все связанные SAS станут недействительными.
Конкурентный доступ
Blob Storage поддерживает оптимистичную конкуренцию через ETag:
var properties = await blobClient.GetPropertiesAsync();
var conditions = new BlobRequestConditions
{
IfMatch = properties.Value.ETag // Update only if not changed
};
try
{
await blobClient.UploadAsync(newData, conditions: conditions);
}
catch (RequestFailedException ex) when (ex.Status == 412)
{
// Blob was modified by another process
Console.WriteLine("Conflict: blob was modified");
}