.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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315779.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AGC026E - Synchronized Subsequence

AGC026E - Synchronized Subsequence 题目描述 Solution 定义cnt[x][0],cnt[x][1]cnt[x][0],cnt[x][1]cnt[x][0],cnt[x][1]表示在前xxx个数中0的个数和1的个数分别是多少。 然后把整个串sss划分为若干个子串&#xff0c;划分点在所有cnt[i][0]cnt[i][1]cnt[i][0]cnt[i][1]c…

[NewLife.XCode]实体工厂(拦截处理实体操作)

NewLife.XCode是一个有10多年历史的开源数据中间件&#xff0c;支持nfx/netcore&#xff0c;由新生命团队(2002~2019)开发完成并维护至今&#xff0c;以下简称XCode。整个系列教程会大量结合示例代码和运行日志来进行深入分析&#xff0c;蕴含多年开发经验于其中&#xff0c;代…

AGC027D - Modulo Matrix

AGC027D - Modulo Matrix 题目描述 Solution 有一个显然的想法是先填一部分格子&#xff0c;剩下的格子的即为相邻格子的LCM1LCM1LCM1&#xff0c;但这样填写的数呈指数级增长&#xff0c;并不优秀。 我们发现一个格子的数是否可以填写只和相邻的四个格子有关系&#xff0c…

DDD该怎么学

2006年&#xff0c;国内的互联网才刚刚萌芽&#xff0c;人们甚至还不习惯网购&#xff0c;大多数在校生都在宿舍里刷魔兽世界副本。但企业软件开发却得到了蓬勃发展&#xff0c;各种公司和事业单位都纷纷进行信息化转型。然而人们很快发现&#xff0c;企业应用业务逻辑的复杂度…

博弈论练习2

博弈论练习2 \;1.AGC010F - Tree Game 题目描述 Solution 一道简单博弈题&#xff08;不知道为啥能作为AGC的F题&#xff09;。 考虑树形dpdpdp&#xff0c;设f[x]f[x]f[x]表示以xxx为根的子树中是否先手必胜。 则f[x]1f[x]1f[x]1当且仅当能找到xxx的子节点vvv满足f[v]0f[v…

Net Core下使用RabbitMQ比较完备两种方案(虽然代码有点惨淡,不过我会完善)

一、前言上篇说给大家来写C#和Java的方案&#xff0c;最近工作也比较忙&#xff0c;迟到了一些&#xff0c;我先给大家补上C#的方案。二、使用的插件HangFire一个开源的.NET任务调度框架&#xff0c;最大特点在于内置提供集成化的控制台,方便后台查看及监控&#xff0c;支持多种…

利用ASP .NET Core的静态文件原理实现远程访问Nlog日志内容及解决遇到的坑

最近项目上试运行发现&#xff0c;很多时候网站出了问题或者某个功能不正常&#xff0c;常常需要运维人员去服务器里面查看一下日志&#xff0c;看看日志里面会产生什么异常&#xff0c;这样导致每次都要去远程服务器很不方便&#xff0c;有时服务器是客户保管的不能让我们随意…

后缀数组SA

后缀数组SA 模板 花了不少时间才理解倍增求SASASA的实现方法&#xff0c;我还是太菜了。 定义sa[i]sa[i]sa[i]表示排名为iii的后缀的起始位置。 定义rank[i]rank[i]rank[i]表示起始位置为iii的后缀的排名。 显然两者之前互逆。 void solve() {int m122;for (int i1;i<m;…

使用.NET Core 编写端到端测试

什么是端到端测试端到端测试也称E2E,与单元测试、集成测试、组件测试、契约测试相比&#xff0c;端到端测试的目的是验证整个系统是否满足业务目标&#xff0c;而不管使用的组件架构如何&#xff0c;为了实现这一点&#xff0c;系统被视为一个黑盒子&#xff0c;测试尽可能多地…

Manacher

Manacher(马拉车算法) Manacher算法主要用于求解回文串问题&#xff0c;能够统计出以每一个位置为中心的回文串的个数&#xff0c;效率极高。 模板 题目描述 Manacher算法的实现过程&#xff1a; 1.在字符串每两个字符之间插入一个分隔符。 2.iii从111到nnn求解P[i]P[i]P[i…

.NET/C# 使用 ConditionalWeakTable 附加字段(CLR 版本的附加属性,也可用用来当作弱引用字典 )...

如果你使用过 WPF/UWP 等 XAML UI 框架&#xff0c;那么应该了解到附加属性的概念。那么没有依赖属性支持的时候如何做附加属性的功能呢&#xff1f;你可能会想到弱引用。但这需要做一个弱引用字典&#xff0c;要写的代码还是非常麻烦的。本文介绍 .NET 的 ConditionalWeakTabl…

P4548 [CTSC2006]歌唱王国

P4548 [CTSC2006]歌唱王国 题目描述 Solution 这一题在《具体数学&#xff08;混泥土数学&#xff09;》里讲得很详细了啊&#xff0c;这里相当于总结一下&#xff0c;想具体了解的直接看书吧。 我们先考虑字符集为222的情况&#xff0c;设硬币正面朝上(H)(H)(H)的概率为pp…

在C#中使用Json.Net进行序列化和反序列化及定制化

序列化&#xff08;Serialize&#xff09;是将对象转换成字节流&#xff0c;并将其用于存储或传输的过程&#xff0c;主要用途是保存对象的状态&#xff0c;以便在需要时重新创建该对象&#xff1b;反序列化&#xff08;Deserialize&#xff09;则是将上面的字节流转换为相应对…

SRM614 Div1 Hard

SRM614 Div1 Hard 题目描述 Solution 显然有&#xff1a; E(x,y)(E(x−1,y)E(x,y−1))/21E(x,y)(E(x-1,y)E(x,y-1))/21 E(x,y)(E(x−1,y)E(x,y−1))/21 直接高斯消元时间复杂度O((nm)3)O((nm)^3)O((nm)3)。 可以发现这种做法十分浪费&#xff0c;消元之后会有大量冗余元素&…

知乎个人精选 | 绝版的专业书到哪里找最快最高效?

估计书到用时方恨少是很多软件开发人员的苦恼&#xff0c;当然我这里提到的"少"表示稀少&#xff0c;买不到之意~比如你加入一家政府机构或给为政府机构服务的公司做开发&#xff0c;主要做传统软件&#xff0c;对方需要使用 Win Forms做开发&#xff0c;你打算系统性…

HUD4035Maze

HUD4035Maze 题目描述 Solution 很容易写出期望的式子&#xff1a; 令fif_ifi​表示从iii号节点开始期望几步走出迷宫。 令pi1−ki−eip_i1-k_i-e_ipi​1−ki​−ei​表示选择走向其他边的概率。 令did_idi​表示iii号结点的度数。 fikif1pi∑fjdi10eiAnsf1f_ik_if_1p_i\sum…

正反案例介绍SOLID原则

一.概述SOLID五大原则使我们能够管理解决大多数软件设计问题。由Robert C. Martin在20世纪90年代编写了这些原则。这些原则为我们提供了从紧耦合的代码和少量封装转变为适当松耦合和封装业务实际需求的结果方法。使用这些原则&#xff0c;我们可以构建一个具有整洁&#xff0c;…

LOJ#2145. 「SHOI2017」分手是祝愿

LOJ#2145. 「SHOI2017」分手是祝愿 题目描述 Solution 首先有一个结论&#xff1a; 灯的状态序列a1,a2...ana_1,a_2...a_na1​,a2​...an​唯一对应了一个最优操作序列b1,b2...bnb_1,b_2...b_nb1​,b2​...bn​。 因为编号最大的灯只能由开关自己来改变。 因此&#xff0c;…

ASP.NET Core 中的静态文件

1.前言当我们创建Core项目的时候&#xff0c;Web根目录下会有个wwwroot文件目录&#xff0c;wwwroot文件目录里面默认有HTML、CSS、IMG、JavaScript等文件&#xff0c;而这些文件都是Core提供给客户端使用的静态文件。但是这些静态文件需要在Core里面配置才可以对外公开访问。2…

LOJ#2542. 「PKUWC2018」随机游走

LOJ#2542. 「PKUWC2018」随机游走 题目描述 Solution 去过一个点集中所有节点的期望时间不好求&#xff0c;考虑min−maxmin-maxmin−max容斥&#xff0c;转化为求第一次到达某一个点集的期望时间。 我们对于每一个点集sss&#xff0c;都求出fif_ifi​表示从iii结点到点集s…