谷歌类浏览器下载asp.netcore3.1静态文件时不能正常保存的问题解决
问题现象:
用谷歌类浏览器访问asp.netcore的静态exe文件不出现保存对话框,而是直接打开一个乱码页面,在其它浏览器中没有遇到这样的问题。
问题环境:
asp.netcore3 + google chrome / edge
解决过程记录:
问题思考:
- 首先浏览器要打开文件需要识别访问到的文件类型,直接在页面显示而不是保存说明返回的类型是需要它直接显示;
- 也就是说显示与否是由获取到的Content-Type来决定的,那么基本可以服务器返回的Content-Type对于它来说是一个不正确的值。
验证:
使用 Fildder2 工具也可以完成此过程。
- 通过F12打开“开发者工具”,到“网络”选项卡;
- 访问一次 exe 的链接;
- 查看链接的Response头信息:
从结果上看 压根没有 Content-Type 这个头。😂
解决问题
通过以上方法已经验证了造成此问题的原因是服务器没有返回Content-Type头,说明服务器不认识exe类型的文件,到代码里验证一下。
- 查看服务器程序开户静态文件的代码处。
app.UseStaticFiles(new StaticFileOptions()
{
ServeUnknownFileTypes = true,
});
这里开启了 ServerUnknownFileTypes 。
现在我们关闭 ServerUnknownFileTypes
app.UseStaticFiles(new StaticFileOptions()
{
ServeUnknownFileTypes = false,
});
- 再访问一次 exe 文件的链接,发现已经不能正确访问了,返回的404
- 查看 StaticFileOptions ,里面两个属性
public IContentTypeProvider ContentTypeProvider { get; set; }
public string DefaultContentType { get; set; }
经测试 这两个属性默认都是null
那么接下来在这两个属性上面想办法就行了。
- 方法一: 通过 ContentTypeProvider 解决:
app.UseStaticFiles(new StaticFileOptions()
{
ServeUnknownFileTypes = true,
ContentTypeProvider=new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider(new System.Collections.Generic.Dictionary<String, String> { { ".exe", "application/octet-stream" } })
});
现在验证一下结果
访问 exe 文件,可以正常下载保存了。
再访问一下静态文件夹里的html页面
再看请求返回的文件头,发现没了 Content-Type
这是因为上面设置的文件类型只包含了 exe 的定义,没有了其它类型,asp.netcore将除exe外的其它静态文件都什么意思不可识别的类型了。
ContentTypeProvider 被覆盖,让程序只认exe类型的文件,其它类型都为不可识别的类型。
此方法可以配合 ServeUnknownFileTypes = false 让客户端只能访问指定类型文件的功能。
- 方法二: 通过直接给Header加Content-Type解决
app.UseStaticFiles(new StaticFileOptions()
{
ServeUnknownFileTypes = true,
OnPrepareResponse = ctx =>
{
var headers = ctx.Context.Response.Headers;
if (ctx.File.Name.ToLower().EndsWith(".exe"))
headers.Append("Content-Type", "application/octet-stream");
}
});
在浏览器访问一下exe文件,可以正常下载保存
再访问一下html页面,也可以正常显示。
此文件可以重定义某个类型文件的 Content-Type
- 方法三: 使用 DefaultContentType 属性
app.UseStaticFiles(new StaticFileOptions()
{
ServeUnknownFileTypes = true,
DefaultContentType= "application/octet-stream"
});
分别访问exe文件和html文件,exe可以正常保存,html页面也可以正常显示。
此方法可以让服务器将所有不识别的文件类型都以 ContentType 返回给浏览器。
以上三种方法可以灵活配置,实现不同的需求。
👨问题解决完毕!!😃😃😃😃😃
🆙🆙🆙🆙
aspnetcore 仓库的源码也确实没有发现 exe 的定义。
FileExtensionContentTypeProvider仓库源码地址