我正在使用Azure存储来提供静态文件斑点,但我想添加一个缓存控制,并在提供时将标题到期,以降低带宽成本。

申请书 CloudXplorer 和小脑 云存储工作室 提供选项以在容器和斑点上设置元数据属性,但在尝试添加高速缓存时会感到沮丧。

有人知道是否可以为文件设置这些标题吗?

有帮助吗?

解决方案

我不得不在约60万个斑点上经营一份批处理,并找到了2件事,这确实有所帮助:

  1. 从同一数据中心中的工人角色运行操作。只要在同一亲和力组中,Azure服务之间的速度就很高。另外,没有数据传输成本。
  2. 并行运行操作。 .NET V4中的任务并行库(TPL)使它非常简单。这是在容器中并行设置每个斑点的高速缓存标头的代码:

    // get the info for every blob in the container
    var blobInfos = cloudBlobContainer.ListBlobs(
        new BlobRequestOptions() { UseFlatBlobListing = true });
    Parallel.ForEach(blobInfos, (blobInfo) =>
    {
        // get the blob properties
        CloudBlob blob = container.GetBlobReference(blobInfo.Uri.ToString());
        blob.FetchAttributes();
    
        // set cache-control header if necessary
        if (blob.Properties.CacheControl != YOUR_CACHE_CONTROL_HEADER)
        {
            blob.Properties.CacheControl = YOUR_CACHE_CONTROL_HEADER;
            blob.SetProperties();
        }
    });
    

其他提示

这是乔尔·菲尔莫尔(Joel Fillmore)答案的更新版本:

Azure现在没有创建网站并使用Workerrole,而是能够运行“ WebJobs”。您可以在同一数据中心的网站上运行任何可执行文件,在该网站上,您的存储帐户的位于设置缓存标头或任何其他标头字段。

  1. 创建一个丢弃的临时网站 在同一数据中心 作为您的存储帐户。不必担心亲和力群体;创建一个空的ASP.NET网站或任何其他简单站点。内容不重要。
  2. 使用下面的代码创建控制台程序,该代码与更新的Azure存储API一起使用。将其编译以进行释放,然后将可执行文件和所有必需的DLL缩减到.zip文件中。
  3. 创建一个WebJob并从步骤2上传.zip文件。enter image description here
  4. 运行WebJob。写在控制台的所有内容都可以在创建的日志文件中查看,并可以从WebJob控制页面访问。
  5. 注意updateazureserviceversion方法。显然,默认情况下,Azure存储的格式不正确,因此您可能希望一次运行此代码,有关详细信息,请参见: 这个

下面的代码为每个容器运行了一个单独的任务,并且我得到的每个容器每秒更新约70个标题。没有出口费。

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;

namespace AzureHeaders
{
    class Program
    {
        static StorageCredentials storageCredentials =
            new StorageCredentials("azureaccountname", @"azzureaccountkey");
        private static string newCacheSettings = "public, max-age=7776000"; // 3 months
        private static string[] containersToProcess = { "container1", "container2" };

        static void Main(string[] args)
        {
            var account = new CloudStorageAccount(
                storageCredentials,
                false /* useHttps */);

            CloudBlobClient blobClient = account.CreateCloudBlobClient();

            var tasks = new List<Task>();
            foreach (var container in blobClient.ListContainers())
            {
                if (containersToProcess.Contains(container.Name))
                {
                    var c = container;
                    tasks.Add(Task.Run(() => FixHeaders(c)));
                }
            }
            Task.WaitAll(tasks.ToArray());
        }

        private static async Task FixHeaders(CloudBlobContainer cloudBlobContainer)
        {
            int totalCount = 0, updateCount = 0, errorCount = 0;

            Console.WriteLine("Starting container: " + cloudBlobContainer.Name);
            IEnumerable<IListBlobItem> blobInfos = cloudBlobContainer.ListBlobs(useFlatBlobListing: true);

            foreach (var blobInfo in blobInfos)
            {
                try
                {
                    CloudBlockBlob blockBlob = (CloudBlockBlob)blobInfo;
                    var blob = await cloudBlobContainer.GetBlobReferenceFromServerAsync(blockBlob.Name);
                    blob.FetchAttributes();

                    // set cache-control header if necessary
                    if (blob.Properties.CacheControl != newCacheSettings)
                    {
                        blob.Properties.CacheControl = newCacheSettings;
                        blob.SetProperties();
                        updateCount++;
                    }
                }
                catch (Exception ex)
                {
                    // Console.WriteLine(ex.Message);
                    errorCount++;
                }
                totalCount++;
            }
            Console.WriteLine("Finished container: " + cloudBlobContainer.Name + 
                ", TotalCount = " + totalCount + 
                ", Updated = " + updateCount + 
                ", Errors = " + errorCount);
        }

        // http://geekswithblogs.net/EltonStoneman/archive/2014/10/09/configure-azure-storage-to-return-proper-response-headers-for-blob.aspx
        private static void UpdateAzureServiceVersion(CloudBlobClient blobClient)
        {
            var props = blobClient.GetServiceProperties();
            props.DefaultServiceVersion = "2014-02-14";
            blobClient.SetServiceProperties(props);
        }
    }
}

最新版本的 小脑云存储工作室, ,v2011.04.23.00,支持在单个斑点对象上设置高速缓存。右键单击blob对象,选择“查看/编辑blob属性”,然后设置该值 Cache-Control 属性。 (例如 public, max-age=2592000).

如果使用卷发检查BLOB对象的HTTP标头,则将看到带有设置的值的高速缓存控制标头。

有时,最简单的答案是最好的答案。如果您只想管理少量斑点,可以使用 Azure管理 更改斑点的标题/元数据。

  1. 点击 贮存, ,然后单击存储帐户名。
  2. 点击 容器 选项卡,然后单击容器。
  3. 单击斑点,然后单击 编辑 在屏幕的底部。

在该编辑窗口中,您可以自定义 缓存控制, 内容编码, 内容语言, , 和更多。

笔记: 您当前无法从 Azure门户

这可能为时已晚,但是最近我想以不同的方式进行相同的操作,我有图像列表,需要使用PowerShell脚本申请(当然,在Azure存储组件的帮助下)希望有人会发现这有用在未来。

完整的解释 使用PowerShell脚本设置Azure Blob Cache-Control

Add-Type -Path "C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\v2.3\ref\Microsoft.WindowsAzure.StorageClient.dll"

$accountName = "[azureaccountname]"
$accountKey = "[azureaccountkey]"
$blobContainerName = "images"

$storageCredentials = New-Object Microsoft.WindowsAzure.StorageCredentialsAccountAndKey -ArgumentList $accountName,$accountKey
$storageAccount = New-Object Microsoft.WindowsAzure.CloudStorageAccount -ArgumentList $storageCredentials,$true
#$blobClient = $storageAccount.CreateCloudBlobClient()
$blobClient =  [Microsoft.WindowsAzure.StorageClient.CloudStorageAccountStorageClientExtensions]::CreateCloudBlobClient($storageAccount)

$cacheControlValue = "public, max-age=604800"

echo "Setting cache control: $cacheControlValue"

Get-Content "imagelist.txt" | foreach {     
    $blobName = "$blobContainerName/$_".Trim()
    echo $blobName
    $blob = $blobClient.GetBlobReference($blobName)
    $blob.Properties.CacheControl = $cacheControlValue
    $blob.SetProperties()
}

设置存储BLOB CACE-CONTROL属性通过PowerShell脚本

https://gallery.technet.microsoft.com/how-to-set-storage-blob-4774aca5

#creat CloudBlobClient 
Add-Type -Path "C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\v2.3\ref\Microsoft.WindowsAzure.StorageClient.dll" 
$storageCredentials = New-Object Microsoft.WindowsAzure.StorageCredentialsAccountAndKey -ArgumentList $StorageName,$StorageKey 
$blobClient =   New-Object Microsoft.WindowsAzure.StorageClient.CloudBlobClient($BlobUri,$storageCredentials) 
#set Properties and Metadata 
$cacheControlValue = "public, max-age=60480" 
foreach ($blob in $blobs) 
{ 
  #set Metadata 
  $blobRef = $blobClient.GetBlobReference($blob.Name) 
  $blobRef.Metadata.Add("abcd","abcd") 
  $blobRef.SetMetadata() 

  #set Properties 
  $blobRef.Properties.CacheControl = $cacheControlValue 
  $blobRef.SetProperties() 
}

这是乔尔·菲尔莫尔(Joel Fillmore)的答案的更新版本,消耗Windowsazure.Starevore v9.3.3。请注意,ListBlobSegendedAsync返回5,000页的页面大小,这就是为什么使用BlobContinuationToken的原因。

    public async Task BackfillCacheControlAsync()
    {
        var container = await GetCloudBlobContainerAsync();
        BlobContinuationToken continuationToken = null;

        do
        {
            var blobInfos = await container.ListBlobsSegmentedAsync(string.Empty, true, BlobListingDetails.None, null, continuationToken, null, null);
            continuationToken = blobInfos.ContinuationToken;
            foreach (var blobInfo in blobInfos.Results)
            {
                var blockBlob = (CloudBlockBlob)blobInfo;
                var blob = await container.GetBlobReferenceFromServerAsync(blockBlob.Name);
                if (blob.Properties.CacheControl != "public, max-age=31536000")
                {
                    blob.Properties.CacheControl = "public, max-age=31536000";
                    await blob.SetPropertiesAsync();
                }
            }               
        }
        while (continuationToken != null);
    }

    private async Task<CloudBlobContainer> GetCloudBlobContainerAsync()
    {
        var storageAccount = CloudStorageAccount.Parse(_appSettings.AzureStorageConnectionString);
        var blobClient = storageAccount.CreateCloudBlobClient();
        var container = blobClient.GetContainerReference("uploads");
        return container;
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top