ASP.NET Core 文件系统
ASP.NET Core 文件系统
紧接上一讲 中间件 之后,今天来我们来讲一下关于 ASP.NET Core 中静态文件服务。
什么是静态文件?
先看一下下面例子(在客户端浏览器中通过 url 路径访问了网站的一张图片):
这样的图片就是一个静态文件
静态文件(staticfiles),其实就是指像 HTML、CSS、图片 和 JavaScript 之类固定的文件,是会被应用程序直接提供给客户端的资源。
静态文件通常位于web root(内容根目录或Web根目录)文件夹下。有关 内容根目录 和 Web根目录 的信息在第一讲中介绍过。
- 内容根目录(Contentroot):是应用程序所用到的所有内容的根路径。WebHost.CreateDefaultBuilder() 中默认下把项目的当前目录设置为内容根目录,也就是指 web 的项目的文件夹,包括 bin 和 webroot 文件夹。
- Web根目录(webroot):项目中用于存放类似于 CSS、JS、图片等公开、静态资源的目录。
- Web根目录默认为的是 Contentroot 路径下的 wwwroot 文件夹。
- 静态文件中间件将默认只读取 Web根目录和其子目录中的文件。
- 对于 Razor (.cshtml) 文件,波浪号斜杠 ~/ 指向 webroot。 以 ~/ 开头的路径称为虚拟路径。
静态文件可以保存在 Web根目录(默认为wwwroot) 下的任意文件夹内,并通过相对根的路径来访问。例如当你通过 VisualStudio 创建一个默认的 Web应用程序(MVC)项目时,在 wwwroot 目录下会多出几个文件夹:css、images以及js。
通过下面的URL就能够直接访问 images 目录下的图片:
http://<app>/images/<imageFileName>
http://localhost:7819/images/banner1.svg
静态文件中间件
如上例子,为了能够使用静态文件的服务,必须配置中间件,把静态文件中间件加入到请求管道内。(默认创建的 MVC Web应用程序已经配置了)
静态文件中间件可通过下述方法来配置:在项目中增加 MicrosoftAspNetCore.StaticFiles 包依赖,然后从Startup.Configure 中调用 app.UseStaticFiles 扩展方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
}
上面我们通过一个简单的实例使用 app.UseStaticFiles() 来使用文件中间件,使得Web根目录下的所有静态文件直接发布出来。如果我们需要发布的静态文件存储在其他目录下呢?依旧是这个应用,现在我们将静态文件放在自定义文件夹 MyStaticFiles 内,并将以Web的形式发布出来,展示如何通过使用 UseStaticFiles 将其他非wwwroot目录下的内容也向外提供服务。
如果要访问 MyStaticFiles 文件夹下的 test.png 图片,可以这样配置静态文件中间件:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions() // 使用 StaticFileOptions 这个对象来初始化静态文件中间件
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")), // 物理文件路径
RequestPath = new PathString("/StaticFiles"), // 请求路径
});
}
ASP.NET Core 一般情况下都是利用一个FileProvider 对象来读取文件的,它在处理针对静态文件的请求是也不例外。
上边代码在静态文件中间件中,在调用静态文件中间件的方法 UseStaticFiles(),该方法可接受一个配置项对象 StaticFileOptions,其内部具有一个 FileProvider 和请求路径的映射关系。
如果调用 UseStaticFiles方法没有指定任何的参数,那么这个映射关系的请求路径就是应用的基地址(PathBase),而FileProvider自然就是指向WebRoot目录的PhysicalFileProvider。
通过访问 http://<app>/StaticFiles/test.png,这样就能访问到 test.png 图片文件了。
静态文件授权 :
静态文件中间件默认不提供授权检查。任何通过该模块提供访问的文件,包括位丁 wwwroot 下的文件都是公开的,那么如何给文件提供授权呢?
将文件保存在 wwwroot 之外,并将目录设置为可被静态文件中间件访问到,同时通过一个 controller action 来访问,通过授权后返回HleResulU将文件保存在wwwroot之外,并将目录设置为可被静态文件中间件访问到,同时通过一个itrolleraction来访问,通过授权后返回 FileResult。
目录浏览
以上通过注册的 StaticFileMiddleware 只会处理针对某个具体静态文件的请求,如果我们向某个目录的URL发送HTTP请求,得到的将是一个状态为404的响应。那是因为基于安全考虑,默认情况下应用程序是禁用目录访问功能的。目录浏览就是允许网站用户看到指定目录下的目录和文件列表。我们可以通过注册一个名为DirectoryBrowserMiddleware 的中间件来显示请求目录的内容:
Step1. 在Startup.ConfigureServices 中调用 AddDirectoryBrowser 扩展方法添加目录浏览服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddDirectoryBrowser();
}
Step2. 然后在 Startup.Configure 中调用 UseDirectoryBrowser 扩展方法使用中间件来开启网络应用目录浏览:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
RequestPath = new PathString("/StaticFiles"),
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
RequestPath = new PathString("/StaticFiles"),
});
}
运行程序后,就可以通过访问 http:<app>/StaticFiles 来浏览 ContentRoot/StaticFiles 文件夹中的目录了。这个中间件会返回一个HTML页面,将请求目录下的所有文件将以表格的形式包含在这个页面中(包括该文件夹下的每一个文件夹与文件)
注意:使用静态文件和目录浏览的区别,上述Step2.Startup.Configure方法中调用了两个 app.UseStaticFiles :第一个调用允许请求 wwwroot 文件夹下的静态文件,第二个调用则是允许通过 http:<app>/StaticFiles/<fileName> 请求 StaticFiles 文件夹中的静态文件,调用 app.UseDirectoryBrowser 则是允许通过 http:<app>/StaticFiles 请求浏览 StaticFiles 文件夹的目录。
注册指定目录的浏览
app.UseDirectoryBrowser 方法可接受一个配置项对象 DirectoryBrowserOptions,该对象与静态文件中间件配置项对象相似,通过该对象可以配置允许用户浏览的目录和请求的虚拟路径。
默认文件
设置默认首页能给站点的每个访问者提供一个默认起始页。为了使站点能够提供默认页面,避免用户输入完整URL,我们可以在 Startup.Configure 中调用 app.UseDefaultFiles 扩展方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseDefaultFiles();
app.UseStaticFiles();
}
app.UseDefaultFiles 必须是在 UseStaticFiles 之前调用。UseDefaultFiles只是重写了URL,而不是真的提供了这样一个文件。因此必须开启静态文件中间件(UseStaticFiles)来提供这个文件。
通过 UseDefanltFiles,请求文件夹的时候将检索以下文件:
- default.htm
- default.html
- index.htm
- index.html
列表中第一个被找到的文件将返回给用户,作为该完整URL的请求的应答,而此时浏览器上URL将继续显示用户输入的URI。
指定默认文件
静态文件中间件可以接受一个 DefaultFilesOptions 的配置对象参数,通过添加默认主页名称,可以指定自定义的默认文件(默认首页),下面的代码展示如何将默认文件名改为 myindex.html
public void Configure(IApplicationBuilder app)
{
DefaultFilesOptions options = new DefaultFilesOptions();
options.DefaultFileNames.Clear(); // 清除默认文件
options.DefaultFileNames.Add("login.html"); //添加指定文件为默认文件
app.UseDefaultFiles(options); //使用默认文件中间件
app.UseStaticFiles(); //使用静态文件中间件(必须)
}
在 web根目录中添加好 login.html 页面,运行程序:
UseFileServer
UseFileServer 集合了 UseStaticFiles、UseDefaultFiles以及UseDirectoryBrowser。
下面的代码启用了静态文件和默认文件,但不允许直接访问目录:
app.UseFileServer();
下面的代码启用了静态文件、默认文件和目录浏览功能:
app.UseFileServer(enableDirectoryBrowsing:true);
作为一个集合了UseStaticFiles、UseDefaultFiles和UseDirectoryBrowser方法于一体的方法,如果希望提供 web根目录之外存在的文件,则需要实例化并配置一个 FileServerOptions 对象传递给app.UscFileServer 的参数。例如,在应用中有如下层次的目录:
对于上面这个层次结构的示例,你可能需耍启用静态文件、默认文件以及浏览 MyStaticFiles 目录等功能。下面的代码片段演示了如何通过调用一次 FileServerOptions 来完整实现这些功能:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseFileServer(new FileServerOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
RequestPath = new PathString("/StaticFiles"),
EnableDirectoryBrowsing = true,
EnableDefaultFiles = true,
});
}
如果将 enableDirectoryBrowsing设置为true,则必须要在 Startup.ConfigureServices 中调用 services.AddDirectoryBrowser 扩展方法:
public void ConfigureServices(IServiceCollection services)
{
services.AddDirectoryBrowser();
}
如果在 MyStaticFiles 目录下存在默认页面,则打开默认页面。如果没有默认命名的文件,则http://StaticFiles将返回目录 StaticFiles 的目录列表,如下图所示。
FileExtensionContentTypeProvider
FileExtensionContentTypeProvider 类内包含一个将文件扩展名映射到 MIME内容类型的集合。在下面的例子中,将多个文件扩展名(如:.myapp)注册为已知的MIME类型(application/x-msdownload),“.rtf”被替换,“.mp4”被移除:
public void Configure(IApplicationBuilder app)
{
FileExtensionContentTypeProvider provider = new FileExtensionContentTypeProvider();
// add new mapping.
provider.Mappings[".myapp"] = "application/x-msdownload";
provider.Mappings[".htm3"] = "text/html";
provider.Mappings[".image"] = "image/png";
// replace an existing mepping.
provider.Mappings[".rtf"] = "application/x-msdownload";
// remove mp4 vidios.
provider.Mappings.Remove(".mp4");
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
RequestPath = new PathString("/StaticFiles"),
ContentTypeProvider = provider,
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
RequestPath = new PathString("/StaticFiles"),
});
}
非标准的内容类型
ASP.NET Core 静态文件中间件能够支持超过400多种己知的文件内容类型。如果用户请求一个未知的文件类型,静态文件中间件将返 HTTP404(未找到)响应。如果启用目录浏览,则该文件的URL将会被显示,但访问URL会返回一个 HTTP404 错误。下面则通过代码把不能识别的类型和文件作为下载的文件处理:
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
RequestPath = new PathString("/StaticFiles"),
ServeUnknownFileTypes = true,
DefaultContentType = "application/x-msdownload",
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
RequestPath = new PathString("/StaticFiles"),
});
}
注意事项:
- UseDirectoryBrowser 和 UseStaticFiles 可能会泄密。建议不要在生产环境开启目录浏览。要小心那些被你开启了 UseStaticFiles 或 UseDirectoryBrowser 的目录,它们的子文件及子目录都可被访问。建议将公开内容放在<content root>/wwwroot 这样的目录中,远离应用程视图、配置文件等。
- 使用 UseDirectoryBrowser 和 UseStaticFiles 暴露的文件的 URL是否区分大小写以及字符限制,受制于底层文件系统。比如Windows是不区分大小写的,但MACOS和Linux则区分大小写。
实战简单文件服务器
① 首先新建一个ASP.NETCore项目,选择空的模板。
② 使用NuGet命令添加Microsoft.AspNetCore.StaticFiles引用:
Install-PackageMicrosoft.AspNetCore.StaticFiles
③ 如果我们的文件服务器需要能访问和浏览E盘的所有文件与文件夹,那么我们就需要用到 UseStaticFiles 和 UseDirectoryBrowser 方法了,在 Startup.Configure 方法下添加如下代码:
public void Configure(IApplicationBuilder app)
{
FileExtensionContentTypeProvider provider = new FileExtensionContentTypeProvider();
provider.Mappings[".log"] = "text/plain";
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(@"E:\"), // 指定静态文件目录
ServeUnknownFileTypes = true,
ContentTypeProvider = provider,
DefaultContentType = "application/x-msdownload", // 设置未识别的MIME类型一个默认z值
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions()
{
FileProvider = new PhysicalFileProvider(@"E:\"), // 制定目录,这里指定 E盘,也可以是其他目录
});
}
然后运行程序,这里选择使用 Kestrel,访问:http://<ip>:5000/,如下图所示:
这样我们就能通过客户端浏览服务器E盘的所有文件及文件夹了。我们还手动设置了未识别的 MIME 类型一个默认值("application/x-msdownload"),当浏览器打开这些未识别类型的文件,就会下载这些文件。像 .log 这样的文件就被手动设置为文本方式,浏览器会直接展示出来。这样我们也就实现了一个简单的文件服务器。
如果想用局域网内其他电脑或手机查看图片或视频文件,则修改Properties文件下 launchSettings.json 配置文件中的应用程序URL就可以实现:
"WebApplication": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://*:5001;http://*:5000", // 这样就可以通过 http:ip:5000访问
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
这样在同一局域网内,在手机上访问 http:ip:5000,就能访问服务器E盘中的文件了。
参考原文
Microsoft 文档 ASP.NET Core 中间件
ASP.NET Core 中间件(Middleware)详解
ASP.NET Core 文件系统的更多相关文章
- kubernetes高级之创建只读文件系统以及只读asp.net core容器
系列目录 使用docker创建只读文件系统 容器化部署对应用的运维带来了极大的方便,同时也带来一些新的安全问题需要考虑.比如黑客入侵到容器内,对容器内的系统级别或者应用级别文件进行修改,会造成难以估量 ...
- [ASP.NET Core 3框架揭秘] 文件系统[1]:抽象的“文件系统”
ASP.NET Core应用 具有很多读取文件的场景,比如配置文件.静态Web资源文件(比如CSS.JavaScript和图片文件等)以及MVC应用的View文件,甚至是直接编译到程序集中的内嵌资源文 ...
- [ASP.NET Core 3框架揭秘] 文件系统[2]:总体设计
在<抽象的"文件系统">中,我们通过几个简单的实例演示从编程的角度对文件系统做了初步的体验,接下来我们继续从设计的角度来进一步认识它.这个抽象的文件系统以目录的形式来组 ...
- [ASP.NET Core 3框架揭秘] 文件系统[4]:程序集内嵌文件系统
一个物理文件可以直接作为资源内嵌到编译生成的程序集中.借助于EmbeddedFileProvider,我们可以采用统一的编程方式来读取内嵌的资源文件,该类型定义在 "Microsoft.Ex ...
- [ASP.NET Core 3框架揭秘] 文件系统[3]:物理文件系统
ASP.NET Core应用中使用得最多的还是具体的物理文件,比如配置文件.View文件以及作为Web资源的静态文件.物理文件系统由定义在NuGet包"Microsoft.Extension ...
- ASP.NET Core 6框架揭秘实例演示[07]:文件系统
ASP.NET Core应用具有很多读取文件的场景,如读取配置文件.静态Web资源文件(如CSS.JavaScript和图片文件等).MVC应用的视图文件,以及直接编译到程序集中的内嵌资源文件.这些文 ...
- ASP.NET Core应用的错误处理[2]:DeveloperExceptionPageMiddleware中间件如何呈现“开发者异常页面”
在<ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式>中,我们通过几个简单的实例演示了如何呈现一个错误页面,这些错误页面的呈现分别由三个对应的中间件来完成,接下来我们将 ...
- ASP.NET Core 1.1 简介
ASP.NET Core 1.1 于2016年11月16日发布.这个版本包括许多伟大的新功能以及许多错误修复和一般的增强.这个版本包含了多个新的中间件组件.针对Windows的WebListener服 ...
- ASP.NET Core框架揭秘(持续更新中…)
之前写了一系列关于.NET Core/ASP.NET Core的文章,但是大都是针对RC版本.到了正式的RTM,很多地方都发生了改变,所以我会将之前发布的文章针对正式版本的.NET Core 1.0进 ...
随机推荐
- Flask最强攻略 - 跟DragonFire学Flask - 第七篇 Flask 中路由系统
Flask中的路由系统其实我们并不陌生了,从一开始到现在都一直在应用 @app.route("/",methods=["GET","POST" ...
- [转]find命令之exec
find是我们很常用的一个Linux命令,但是我们一般查找出来的并不仅仅是看看而已,还会有进一步的操作,这个时候exec的作用就显现出来了. exec解释: -exec 参数后面跟的是comm ...
- Python 爬虫学习
#coding:utf-8 #author:Blood_Zero ''' 1.获取网页信息 2.解决编码问题,通过charset库(默认不安装这个库文件) ''' import urllib impo ...
- 2017/05/02 java 基础 随笔
1.PrtSc键是截屏键 打开画图软件 ctrl+v就可以复制到 2.win7以上可以 在当前目录下shift+右键 3.junit和javaweb应用的main函数在哪里? java程序跑起 ...
- 【转】C++ map的基本操作和使用
1.map简介 map是一类关联式容器.它的特点是增加和删除节点对迭代器的影响较小,除了那个操作节点,对其它的节点都没有什么影响.对于迭代器来说,可以修改实值,而不能修改key. 2.map的功能 自 ...
- 读SRE Google运维解密有感(一)
前言 这几天打算利用碎片时间读了一下"SRE Google运维解密"这本书,目前读了前几章,感觉收获颇多,结合自己的工作经历和书中的要点,写一些感悟和思考 SRE 有关SRE我就不 ...
- zabbix通过简单命令监控elasticsearch集群状态
简单命令监控elasticsearch集群状态 原理: 使用curl命令模拟访问任意一个es节点可以反馈的集群状态,集群的状态需要为green curl -sXGET http://serverip: ...
- nagios系列(一)centos6.5环境部署nagios服务端
nagios软件安装包存放目录:/home/oldboy/tools nagios服务安装目录:/usr/local/nagios 1.配置yum源 echo "------ step 1: ...
- activiti 基础
一:activiti 入门 作者:fenng 商丘 工作流(Workflow) 就是业务过程的部分或整体在计算机应用环境下的自动化主要解决的是"使在多个参与者之间按照某种定义的规则传递文档, ...
- PHP对Url中的汉字进行编码和解码
有的新手朋友们对于url编码解码这个概念,或许有点陌生.但是如果这么说,当我们在浏览各大网页时,可能发现有的url里有一些特殊符号比如#号,&号,_号或者汉字等等,那么为了符合url的规范,存 ...