ASP.NET Core 中文文档 第三章 原理(3)静态文件处理
原文:Working with Static Files
作者:Rick Anderson
翻译:刘怡(AlexLEWIS)
校对:谢炀(kiler398)、许登洋(Seay)、孟帅洋(书缘)
静态文件(static files),诸如 HTML、CSS、图片和 JavaScript 之类的资源会被 ASP.NET Core 应用直接提供给客户端。
章节:
静态文件服务
静态文件通常位于 web root
(<content-root>/wwwroot
)文件夹下。更多有关 Content root 或 Web root 的信息请访问 intro 。你通常会把项目的当前目录设置为 Content root,这样项目的 web root
就可以在开发阶段被明确。
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory()) //手工高亮
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
静态文件能够被保存在网站根目录下的任意文件夹内,并通过相对根的路径来访问。比方说,当你通过 Visual Studio 创建一个默认的 Web 应用程序项目,在 wwwroot 目录下会多出几个文件夹:css、images 以及 js 文件夹。形如下例的 URL 能够直接访问 images
目录下的图片:
http://<app>/images/<imageFileName>
http://localhost:9189/images/banner3.svg
为了能够启用静态文件服务,你必须配置中间件(middleware),把静态文件中间件加入到管道内。静态文件中间件能够通过下述方法来配置:在你的项目中增加 Microsoft.AspNetCore.StaticFiles 包依赖,然后从 Startup.Configure
调用 UseStaticFiles 扩展方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseStaticFiles(); //手工高亮
}
app.UseStaticFiles();
使得 web root
(默认为 wwwroot)下的文件可以被访问。随后我将展示如何通过使用 UseStaticFiles
将其他目录下的内容也向外提供服务。
你必须在 project.json 文件中包含 “Microsoft.AspNetCore.StaticFiles”。
注意
web root
的默认目录是 wwwroot,但你可以通过 UseWebRoot 来设置web root
。具体可参考 intro 。
假设你有一个有层次结构的项目,你希望其中静态文件的位于 web root
的外部,比如:
wwwroot
- css
- images
- ...
MyStaticFiles
- test.png
对于访问 test.png 的请求,可以如此配置静态文件中间件:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions() //手工高亮
{ //手工高亮
FileProvider = new PhysicalFileProvider( //手工高亮
Path.Combine(Directory.GetCurrentDirectory(), @"MyStaticFiles")), //手工高亮
RequestPath = new PathString("/StaticFiles") //手工高亮
}); //手工高亮
}
在请求 http://<app>/StaticFiles/test.png
时,就能访问到 test.png 文件。
静态文件授权
静态文件模块并 不 提供授权检查。任何通过该模块提供访问的文件,包括位于 wwwroot 下的文件都是公开的。为了给文件提供授权:
- 将文件保存在 wwwroot 之外并将目录设置为可被静态文件中间件访问到,同时——
- 通过一个控制器的 Action 来访问它们,通过授权后返回 FileResult
允许直接浏览目录
目录浏览允许网站用户看到指定目录下的目录和文件列表。基于安全考虑,默认情况下是禁用目录访问功能的(参考 注意事项 )。在 Startup.Configure
中调用 UseDirectoryBrowser 扩展方法可以开启网络应用目录浏览:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseStaticFiles(); // For the wwwroot folder
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
RequestPath = new PathString("/MyImages")
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
RequestPath = new PathString("/MyImages")
});
}
并且通过从 Startup.ConfigureServices
调用 AddDirectoryBrowser 扩展方法来增加所需服务。
public void ConfigureServices(IServiceCollection services)
{
services.AddDirectoryBrowser();
}
这段代码允许在访问 http://<app>/MyImages
时可浏览 wwwroot/images 文件夹的目录,其中包括该文件夹下的每一个文件与文件夹:
查看关于开放访问目录时的安全隐患 注意事项 一节。
注意两个 app.UseStaticFiles
调用。第一个调用请求 wwwroot 文件夹下的 CSS、图片和 JavaScript,第二个调用通过 http://<app>/MyImages
请求浏览 wwwroot/images 文件夹的目录
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseStaticFiles(); // For the wwwroot folder //手工高亮
app.UseStaticFiles(new StaticFileOptions() //手工高亮
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
RequestPath = new PathString("/MyImages")
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
RequestPath = new PathString("/MyImages")
});
}
默认文档服务
设置默认首页能给你的站点的每个访问者提供一个起始页。为使站点能提供默认页,避免用户输入完整 URI,须在 Startup.Configure
中调用 UseDefaultFiles
扩展方法:
public void Configure(IApplicationBuilder app)
{
app.UseDefaultFiles(); //手工高亮
app.UseStaticFiles();
}
注意
UseDefaultFiles 必须在UseStaticFiles
之前调用。UseDefaultFiles
只是重写了 URL,而不是真的提供了这样一个文件。你必须开启静态文件中间件(UseStaticFiles
)来提供这个文件。
通过 UseDefaultFiles,请求文件夹的时候将检索以下文件:
- default.htm
- default.html
- index.htm
- index.html
上述列表中第一个被找到的文件将返回给用户(作为该完整 URI 的请求的应答,而此时浏览器 URL 将继续显示用户输入的 URI)。
下述代码展示如何将默认文件名改为 mydefault.html 。
public void Configure(IApplicationBuilder app)
{
// Serve my app-specific default file, if present.
DefaultFilesOptions options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
}
UseFileServer
UseFileServer 包含了 UseStaticFiles 、UseDefaultFiles 和 UseDirectoryBrowser 的功能。
下面的代码启用了静态文件和默认文件,但不允许直接访问目录:
app.UseFileServer();
下面的代码启用了静态文件、默认文件和目录浏览功能:
app.UseFileServer(enableDirectoryBrowsing: true);
查看直接提供目录访问时的安全风险注意事项。作为一个集合了 UseStaticFiles
、UseDefaultFiles
和 UseDirectoryBrowser
方法于一体的方法,如果你希望提供 web root
之外存在的文件,你要实例化并配置一个 FileServerOptions 对象传递给 UseFileServer
的参数。比方说在你的应用中有如下层次的目录:
wwwroot
- css
- images
- ...
MyStaticFiles
- test.png
- default.html
使用上面这个层次结构的示例,你可能希望启用静态文件、默认文件以及浏览 MyStaticFiles
目录。下面的代码片段演示了调用一次 FileServerOptions 来完整实现这些功能:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseStaticFiles();
app.UseFileServer(new FileServerOptions() //手工高亮
{ //手工高亮
FileProvider = new PhysicalFileProvider( //手工高亮
Path.Combine(Directory.GetCurrentDirectory(), @"MyStaticFiles")), //手工高亮
RequestPath = new PathString("/StaticFiles"), //手工高亮
EnableDirectoryBrowsing = true //手工高亮
}); //手工高亮
}
如果在你从 Startup.ConfigureServices
请求调用 AddDirectoryBrowser 扩展方法时将 enableDirectoryBrowsing
置为 true
,那么:
public void ConfigureServices(IServiceCollection services)
{
services.AddDirectoryBrowser();
}
使用的文件层次结构:
URI | Response |
---|---|
http://<app>/StaticFiles/test.png |
StaticFiles/test.png |
http://<app>/StaticFiles |
MyStaticFiles/default.html |
如果在 MyStaticFiles 目录下没有默认命名的文件,则 http://<app>/StaticFiles
将返回目录列表,其中包含可供点击的链接:
注意
UseDefaultFiles
和UseDirectoryBrowser
将会把末尾不带斜杠的 URLhttp://<app>/StaticFiles
重新定向到http://<app>/StaticFiles/
(末尾增加了一个斜杠)。如果末尾不带斜杠,文档内相对 URL 会出错。
FileExtensionContentTypeProvider
FileExtensionContentTypeProvider 类内包含一个将文件扩展名映射到 MIME 内容类型的集合。在下面的例子中,多个文件扩展名注册为已知的 MIME 类型,“.rtf”被替换,“.mp4”被移除。
public void Configure(IApplicationBuilder app)
{
// Set up custom content types -associating file extension to MIME type //手工高亮
var provider = new FileExtensionContentTypeProvider(); //手工高亮
// Add new mappings //手工高亮
provider.Mappings[".myapp"] = "application/x-msdownload"; //手工高亮
provider.Mappings[".htm3"] = "text/html"; //手工高亮
provider.Mappings[".image"] = "image/png"; //手工高亮
// Replace an existing mapping //手工高亮
provider.Mappings[".rtf"] = "application/x-msdownload"; //手工高亮
// Remove MP4 videos. //手工高亮
provider.Mappings.Remove(".mp4"); //手工高亮
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
RequestPath = new PathString("/MyImages"),
ContentTypeProvider = provider //手工高亮
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
RequestPath = new PathString("/MyImages")
});
}
查看 MIME 内容类型。
非标准的内容类型
ASP.NET 静态文件中间件能够支持超过 400 种已知文件内容类型。如果用户请求一个未知的文件类型,静态文件中间件将返回 HTTP 404(未找到)响应。如果启用目录浏览,该文件的链接将会被显示,但 URI 会返回一个 HTTP 404 错误。
下方代码把不能识别的类型和文件作为图片处理。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "image/png"
});
}
根据上面的代码,未知内容类型的文件请求将返回一张图片。
警告
开启 ServeUnknownFileTypes 存在安全风险,请打消这个念头。 FileExtensionContentTypeProvider (下文将解释)提供了更安全的非标准扩展替代。
注意事项
警告
UseDirectoryBrowser
和UseStaticFiles
可能会泄密。我们推荐你 不要 在生产环境开启目录浏览。要小心哪些被你开启了UseStaticFiles
或UseDirectoryBrowser
的目录(使得其子目录都可被访问)。我们建议将公开内容放在诸如<content root>/wwwroot
这样的目录中,远离应用程序视图、配置文件等。
使用
UseDirectoryBrowser
和UseStaticFiles
暴露的文件的 URL 是否区分大小写以及字符限制受制于底层文件系统。比方说 Windows 是不区分大小写的,但 macOS 和 Linux 则区分大小写。托管于 IIS 的 ASP.NET Core 应用程序使用 ASP.NET Core 模块向应用程序转发所有请求,包括静态文件。IIS 静态文件处理程序(IIS Static File Handler)不会被使用,因为在 ASP.NET Core 模块处理之前它没有任何机会来处理请求。
以下步骤可移除 IIS 静态文件处理程序(在服务器层级或网站层级上):
- 导航到 模块 功能
- 从列表中选中 StaticFileModule
- 在 操作 侧边栏中点击 删除
警告
如果 IIS 静态文件处理程序开启 并且 ASP.NET Core 模块(ANCM)没有被正确配置(比方说 web.config 没有部署),(也能)将会提供静态文件。
- 代码文件(包括 C# 和 Razor)应该放在应用程序项目的
web root
(默认为 wwwroot)之外的地方。这将确保您创建的应用程序能明确隔离客户端侧和服务器侧源代码,此举能防止服务器侧的代码被泄露。
扩展资源
ASP.NET Core 中文文档 第三章 原理(3)静态文件处理的更多相关文章
- ASP.NET Core 中文文档 第三章 原理(6)全球化与本地化
原文:Globalization and localization 作者:Rick Anderson.Damien Bowden.Bart Calixto.Nadeem Afana 翻译:谢炀(Kil ...
- ASP.NET Core 中文文档 第三章 原理(1)应用程序启动
原文:Application Startup 作者:Steve Smith 翻译:刘怡(AlexLEWIS) 校对:谢炀(kiler398).许登洋(Seay) ASP.NET Core 为你的应用程 ...
- ASP.NET Core 中文文档 第三章 原理(13)管理应用程序状态
原文:Managing Application State 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:高嵩 在 ASP.NET Core 中,有多种途径可以对应用程序的状态进行 ...
- ASP.NET Core 中文文档 第三章 原理(2)中间件
原文:Middleware 作者:Steve Smith.Rick Anderson 翻译:刘怡(AlexLEWIS) 校对:许登洋(Seay) 章节: 什么是中间件 用 IApplicationBu ...
- ASP.NET Core 中文文档 第三章 原理(10)依赖注入
原文:Dependency Injection 作者:Steve Smith 翻译:刘浩杨 校对:许登洋(Seay).高嵩 ASP.NET Core 的底层设计支持和使用依赖注入.ASP.NET Co ...
- ASP.NET Core 中文文档 第三章 原理(11)在多个环境中工作
原文: Working with Multiple Environments 作者: Steve Smith 翻译: 刘浩杨 校对: 孟帅洋(书缘) ASP.NET Core 介绍了支持在多个环境中管 ...
- ASP.NET Core 中文文档 第三章 原理(17)为你的服务器选择合适版本的.NET框架
原文:Choosing the Right .NET For You on the Server 作者:Daniel Roth 翻译:王健 校对:谢炀(Kiler).何镇汐.许登洋(Seay).孟帅洋 ...
- ASP.NET Core 中文文档 第三章 原理(7)配置
原文:Configuration 作者:Steve Smith.Daniel Roth 翻译:刘怡(AlexLEWIS) 校对:孟帅洋(书缘) ASP.NET Core 支持多种配置选项.应用程序配置 ...
- ASP.NET Core 中文文档 第三章 原理(8)日志
原文:Logging 作者:Steve Smith 翻译:刘怡(AlexLEWIS) 校对:何镇汐.许登洋(Seay) ASP.NET Core 内建支持日志,也允许开发人员轻松切换为他们想用的其他日 ...
随机推荐
- iOS热更新-8种实现方式
一.JSPatch 热更新时,从服务器拉去js脚本.理论上可以修改和新建所有的模块,但是不建议这样做. 建议 用来做紧急的小需求和 修复严重的线上bug. 二.lua脚本 比如: wax.热更新时,从 ...
- 转:聊聊mavenCenter和JCenter
Gradle支持从maven中央仓库和JCenter上获取构件,那这两者有什么区别呢? maven中央仓库(http://repo1.maven.org/maven2/)是由Sonatype公司提供的 ...
- Android数据加密之Base64编码算法
前言: 前面学习总结了平时开发中遇见的各种数据加密方式,最终都会对加密后的二进制数据进行Base64编码,起到一种二次加密的效果,其实呢Base64从严格意义上来说的话不是一种加密算法,而是一种编码算 ...
- ES6的一些常用特性
由于公司的前端业务全部基于ES6开发,于是给自己开个小灶补补ES6的一些常用特性.原来打算花两天学习ES6的,结果花了3天才勉强过了一遍阮老师的ES6标准入门(水好深,ES6没学好ES7又来了...) ...
- Windows下Visual studio 2013 编译 Audacity
编译的Audacity版本为2.1.2,由于实在windows下编译,其源代码可以从Github上取得 git clone https://github.com/audacity/audacity. ...
- C++ 事件驱动型银行排队模拟
最近重拾之前半途而废的C++,恰好看到了<C++ 实现银行排队服务模拟>,但是没有实验楼的会员,看不到具体的实现,正好用来作为练习. 模拟的是银行的排队叫号系统,所有顾客以先来后到的顺序在 ...
- 【微信小程序开发•系列文章六】生命周期和路由
这篇文章理论的知识比较多一些,都是个人观点,描述有失妥当的地方希望读者指出. [微信小程序开发•系列文章一]入门 [微信小程序开发•系列文章二]视图层 [微信小程序开发•系列文章三]数据层 [微信小程 ...
- H3 BPM:为石化企业提供一个不一样的全停大修平台
H3 BPM大型炼化企业装置全停检修管理平台(简称"全停大修")结合国际化的流程管理理念.成熟的系统技术架构.优秀的行业解决方案,为石油化工行业全停大修提供了卓越的信息化管理方案, ...
- XAMARIN.ANDROID SIGNALR 实时消息接收发送示例
SignalR 是一个开发实时 Web 应用的 .NET 类库,使用 SignalR 可以很容易的构建基于 ASP.NET 的实时 Web 应用.SignalR 支持多种服务器和客户端,可以 Host ...
- 转: 如何高效利用GitHub
注:写了很多使用哲学,有意思 from: http://www.yangzhiping.com/tech/github.html