这里是 Joel Fillmore 的答案的更新版本,使用 Net 5 和 Azure.Storage.Blobs 的 V12。(顺带说一句:如果可以在父容器上设置默认标题属性,那不是太好了吗?)
Azure 不需要创建网站并使用 WorkerRole,而是具有运行“WebJobs”的功能。您可以在位于与存储帐户相同数据中心的网站上按需运行任何可执行文件,以设置缓存标头或任何其他标头字段。
1. 创建一个丢弃的临时网站,
与您的存储账户在同一个数据中心。不用担心亲和性组;创建一个空的 ASP.NET 网站或任何其他简单的网站。内容不重要。我需要使用至少 B1 服务计划,否则 WebJob 在 5 分钟后会中止。
2. 使用下面的代码创建控制台程序,并为发布编译它,然后将可执行文件和所有必需的 DLL 打包成 .zip 文件,或者直接从 VisualStudio 发布并跳过第 3 步。
3. 创建 WebJob 并上传步骤 #2 中的 .zip 文件。
4. 运行 WebJob。控制台中写入的所有内容都可在创建的日志文件中查看,并可从 WebJob 控制页面访问。
![enter image description here](https://istack.dev59.com/LRtSO.webp)
5. 删除临时网站,或将其更改为免费版(在“扩展”下)。
下面的代码为每个容器运行单独的任务,我每分钟更新了多达 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";
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)));
}
Task.WaitAll(tasks.ToArray());
}
private static async Task UpdateHeaders(BlobContainerClient blobContainerClient, int? segmentSize)
{
int processed = 0;
int failed = 0;
try
{
var resultSegment = blobContainerClient.GetBlobsAsync()
.AsPages(default, segmentSize);
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
{
ContentType = propertiesResponse.Value.ContentType,
ContentHash = propertiesResponse.Value.ContentHash,
ContentEncoding = propertiesResponse.Value.ContentEncoding,
ContentDisposition = propertiesResponse.Value.ContentDisposition,
CacheControl = newCacheControl
};
await blobClient.SetHttpHeadersAsync(httpHeaders);
}
}
}