zoukankan      html  css  js  c++  java
  • ASP.NET Core 文件系统

      ASP.NET Core 文件系统

    紧接上一讲 中间件 之后,今天来我们来讲一下关于 ASP.NET  Core 中静态文件服务。


    什么是静态文件?

    先看一下下面例子(在客户端浏览器中通过 url 路径访问了网站的一张图片):

     


     

     

    这样的图片就是一个静态文件

     


     

     

    • 静态文件(staticfiles),其实就是指像 HTMLCSS图片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 集合了 UseStaticFilesUseDefaultFiles以及UseDirectoryBrowser
    下面的代码启用了静态文件和默认文件,但不允许直接访问目录:

    app.UseFileServer();
    

    下面的代码启用了静态文件、默认文件和目录浏览功能:

    app.UseFileServer(enableDirectoryBrowsing:true);
    

    作为一个集合了UseStaticFilesUseDefaultFilesUseDirectoryBrowser方法于一体的方法,如果希望提供 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 的目录列表,如下图所示。

     

    StaticFiles中存在默认页面
    StaticFiles中存在默认页面

     

     

    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盘的所有文件与文件夹,那么我们就需要用到 UseStaticFilesUseDirectoryBrowser 方法了,在 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)详解

  • 相关阅读:
    HTB-靶机-Charon
    第一篇Active Directory疑难解答概述(1)
    Outlook Web App 客户端超时设置
    【Troubleshooting Case】Exchange Server 组件状态应用排错?
    【Troubleshooting Case】Unable to delete Exchange database?
    Exchange Server 2007的即将生命周期,您的计划是?
    "the hypervisor is not running" 故障
    Exchange 2016 体系结构
    USB PE
    10 months then free? 10个月,然后自由
  • 原文地址:https://www.cnblogs.com/anayigeren/p/10282441.html
Copyright © 2011-2022 走看看