これは、Azure.Storage.BlobsのNet5とV12を使用したJoelFillmoreの回答の更新バージョンです。(余談ですが、デフォルトのヘッダープロパティを親コンテナに設定できたら素晴らしいと思いませんか?)
Webサイトを作成してWorkerRoleを使用する代わりに、Azureには「WebJobs」を実行する機能があります。ストレージアカウントが配置されているのと同じデータセンターのWebサイトで実行可能ファイルをオンデマンドで実行して、キャッシュヘッダーまたはその他のヘッダーフィールドを設定できます。
- ストレージアカウントと同じデータセンターに使い捨ての一時的なウェブサイトを作成します。アフィニティグループについて心配する必要はありません。空のASP.NETサイトまたはその他の単純なサイトを作成します。内容は重要ではありません。少なくともB1サービスプランを使用する必要がありました。そうしないと、WebJobが5分後に中止されました。
- 更新されたAzureStorageAPIで動作する以下のコードを使用して、コンソールプログラムを作成します。リリース用にコンパイルしてから、実行可能ファイルと必要なすべてのDLLを.zipファイルに圧縮するか、VisualStudioから公開して以下の#3をスキップします。
- WebJobを作成し、手順2の.zipファイルをアップロードします。
- WebJobを実行します。コンソールに書き込まれたものはすべて、作成されたログファイルで表示でき、WebJobコントロールページからアクセスできます。

- 一時的なWebサイトを削除するか、無料枠([スケールアップ]の下)に変更します。
以下のコードは、コンテナーごとに個別のタスクを実行し、1分あたり最大100Kのヘッダーを更新しています(時刻によって異なりますか?)。下り料金はありません。
using Azure;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace AzureHeaders
{
class Program
{
private static string connectionString = "DefaultEndpointsProtocol=https;AccountName=REPLACE_WITH_YOUR_CONNECTION_STRING";
private static string newCacheControl = "public, max-age=7776001"; // 3 months
private static string[] containersToProcess = { "container1", "container2" };
static async Task Main(string[] args)
{
BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
var tasks = new List<Task>();
foreach (var container in containersToProcess)
{
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(container);
tasks.Add(Task.Run(() => UpdateHeaders(containerClient, 1000))); // I have no idea what segmentSize should be!
}
Task.WaitAll(tasks.ToArray());
}
private static async Task UpdateHeaders(BlobContainerClient blobContainerClient, int? segmentSize)
{
int processed = 0;
int failed = 0;
try
{
// Call the listing operation and return pages of the specified size.
var resultSegment = blobContainerClient.GetBlobsAsync()
.AsPages(default, segmentSize);
// Enumerate the blobs returned for each page.
await foreach (Azure.Page<BlobItem> blobPage in resultSegment)
{
var tasks = new List<Task>();
foreach (BlobItem blobItem in blobPage.Values)
{
BlobClient blobClient = blobContainerClient.GetBlobClient(blobItem.Name);
tasks.Add(UpdateOneBlob(blobClient));
processed++;
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine($"Container {blobContainerClient.Name} processed: {processed}");
}
}
catch (RequestFailedException e)
{
Console.WriteLine(e.Message);
failed++;
}
Console.WriteLine($"Container {blobContainerClient.Name} processed: {processed}, failed: {failed}");
}
private static async Task UpdateOneBlob(BlobClient blobClient) {
Response<BlobProperties> propertiesResponse = await blobClient.GetPropertiesAsync();
BlobHttpHeaders httpHeaders = new BlobHttpHeaders
{
// copy any existing headers you wish to preserve
ContentType = propertiesResponse.Value.ContentType,
ContentHash = propertiesResponse.Value.ContentHash,
ContentEncoding = propertiesResponse.Value.ContentEncoding,
ContentDisposition = propertiesResponse.Value.ContentDisposition,
// update CacheControl
CacheControl = newCacheControl
};
await blobClient.SetHttpHeadersAsync(httpHeaders);
}
}
}