.NET Core 批量重置 Azure Blob Storage 的 mime type

点击上方蓝字关注“汪宇杰博客”

640?wx_fmt=png

我的博客使用 Azure Blob Storage 存储文章配图,结果今天玩 Azure CDN 的时候爆了,原因是图片mime type不对。我们来看看如何在 .NET Core 里批量重置 Azure Blob Storage 中文件的mime type吧。

640?wx_fmt=gif

起因

使用编程方式(Azure Storage API)上传的文件,如果不指定 ContentType ,那么 Azure 不会聪明到根据文件拓展名设置 ContentType 。这个 ContentType 最终就是输出给浏览器的HTTP Header中的content-type,即Web服务器上的mime type。对于没有设置 ContentType 的文件,直接访问 Azure Blob 的地址,会返回"application/octet-stream"。不同浏览器对此处理方式不一样,大部分浏览器会调用文件下载,而不是打开文件。于是,图片就没法显示了。

我博客中的配图,以前之所以没问题,是因为没有使用CDN让客户端直接读取图片,而是通过后台处理,会自动加上正确的mime type,因此这个问题一直没暴露。

获取文件的 ContentType

.NET Core 没有 MimeMapping.GetMimeMapping() 这个API,因此我们需要一个workaround。

感谢长沙.NET技术社区成员 @刘命汉 的发现以及 @周杰 的验证,ASP.NET Core 自带的 FileExtensionContentTypeProvider 是个可替代方案。

var pvd = new FileExtensionContentTypeProvider();

bool isKnownType = pvd.TryGetContentType("test.png", out string mimeType);

// mimeType: "image/png"

对于不认识的拓展名,TryGetContentType() 会返回 false | null

CloudBlockBlob 不设置 ContentType 的话会返回默认的 application/octet-stream,因此null不影响。

640?wx_fmt=gif

更改文件的 ContentType

对于已经上传到 Azure Blob Storage 的文件,可以通过编程方式更改 ContentType 。获取到 CloudBlockBlob 对象以后,设置 Properties.ContentType,然后调用 SetPropertiesAsync() 方法保存更改即可。

对于未上传到Azure的文件,设置完 ContentType 以后,不需要调用 SetPropertiesAsync(), 上传操作 UploadFromStreamAsync() 会带上这些属性。

参见我博客代码commit: https://github.com/EdiWang/Moonglade/commit/3508e35055ae33b2c2241d93f615283a109bad85

自制开源工具

我今天抽空写了个批量重置 Azure Blob Storage 文件Mime Type 的工具,已在 GitHub 开源:

https://github.com/EdiWang/Azure-Blob-MimeType-Reset

关键代码

获取 CloudBlobContainer

有了 CloudBlobContainer 才能遍历里面的文件

private static CloudBlobContainer GetBlobContainer()

{

    CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(Options.AccountName, Options.AccountKey), true);

    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

    CloudBlobContainer container = blobClient.GetContainerReference(Options.ContainerName);

    return container;

}

修改ContentType

此处我做了个判断,只有 ContentType 不正确的文件,才重置 ContentType

private static CloudBlockBlob TrySetContentType(CloudBlockBlob blob, string contentType)

{

    if (blob.Properties.ContentType.ToLower() != contentType)

    {

        blob.Properties.ContentType = contentType;

        return blob;

    }

    return null;

}

遍历文件及提交更改

var pvd = new FileExtensionContentTypeProvider();

WriteMessage($"[{DateTime.Now}] Updating Mime Type...");

int affectedFilesCount = 0;


foreach (var blob in BlobContainer.ListBlobs().OfType<CloudBlockBlob>())

{

    string extension = Path.GetExtension(blob.Uri.AbsoluteUri).ToLower();

    bool isKnownType = pvd.TryGetContentType(extension, out string mimeType);

    if (isKnownType)

    {

        if (TrySetContentType(blob, mimeType) != null)

        {

            WriteMessage($"[{DateTime.Now}] Updating {blob.Uri.AbsoluteUri} => {mimeType}");

            await blob.SetPropertiesAsync();

            affectedFilesCount++;

        }

    }

}

640?wx_fmt=png

参考文档:http://www.thepatrickdavis.com/blob-storage-dont-forget-the-mime/

640?wx_fmt=gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值