zoukankan      html  css  js  c++  java
  • asp.net core 系列之静态文件

    这篇讲解asp.net core中的静态文件(大致翻译于官网)。

    静态文件,例如HTML,CSS, images和JavaScript. 要想直接被客户端访问,需要做一些配置。

    一.Serve static files(提供静态文件服务)

    静态文件存储在项目的web root 目录下默认的目录是<content_root>/wwwroot,但可以通过UseWebRoot方法来改变默认目录

    更多可以查看: See Content root and Web root for more information.

    应用的web host 必须知道内容根目录。

    WebHost.CreateDefaultBuilder方法设置内容根目录到当前目录中

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }

    静态文件可以通过一个相对web root的路径来访问

    例如,web application 项目模板在wwwroot文件夹下包含几个文件夹:

    • wwwroot
      • css
      • images
      • js

    到images子目录中的文件的URI格式为:http://<server_address>/images/<image_file_name> 。 例如

    http://localhost:9189/images/banner3.svg.

    如果是.NET Framework, 添加 Microsoft.AspNetCore.StaticFiles包到项目中。如果是.NET Core, Microsoft.AspNetCore.App包含这个包。

    配置中间件来允许提供静态文件的服务

    1.Serve files inside of web root(在web root中提供files服务)

    在Startup.Configure中调用UseStaticFiles方法

    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticFiles();
    }

    这个无参的UseStaticFiles方法标志着web root中的文件可以提供服务。下面的标签引用 wwwroot/images/banner1.svg:

    <img src="~/images/banner1.svg" alt="ASP.NET" class="img-responsive" />

    在上面的代码中,~/ 指向webroot,更多信息:Web root.

    像上面的代码,要使用web root下的文件,需要直接指向到web root下的具体的文件

    2.Serve files outside of web root(在web root外提供文件服务)

    考虑下面的目录层级,将在web root外面的MyStaticFiles提供文件服务

    通过配置静态文件中间件(the Static File Middleware),使请求可以取得banner1.svg文件:

    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticFiles(); // For the wwwroot folder
    
        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
            RequestPath = "/StaticFiles"
        });
    }

    在上面的代码中,MyStaticFiles目录通过StaticFiles URI被暴露

    一个 到http://<server_address>/StaticFiles/images/banner1.svg 的请求,可以得到banner1.svg文件。

    下面的标记引用MyStaticFiles/images/banner1.svg文件:

    <img src="~/StaticFiles/images/banner1.svg" alt="ASP.NET" class="img-responsive" />

    3.Set HTTP response headers(设置HTTP响应头)

    StaticFileOptions 对象可以被用来设置HTTP response headers(HTTP 响应头)

    另外配置静态文件服务于web root, 下面的代码设置了Cache-Control 头:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        var cachePeriod = env.IsDevelopment() ? "600" : "604800";
        app.UseStaticFiles(new StaticFileOptions
        {
            OnPrepareResponse = ctx =>
            {
                // Requires the following import:
                // using Microsoft.AspNetCore.Http;
                ctx.Context.Response.Headers.Append("Cache-Control", $"public, max-age={cachePeriod}");
            }
        });
    }

    HeaderDictionaryExtensions.Append方法存在于Microsoft.AspNetCore.Http包中。

    这个文件在开发环境可以缓存10分钟(600秒)。

    二.Static file authorization(静态文件授权)

    静态文件中间件不会提供授权检查。任何被它提供的文件服务,包括在wwwroot下的,都是公开可以访问的。

    要基于授权提供文件服务

    • 把它们存储在wwwroot外面 和 对于静态文件中间件可以到达的任意目录
    • 通过认证的action方法提供它们。返回一个FileResult对象:
    [Authorize]
    public IActionResult BannerImage()
    {
        var file = Path.Combine(Directory.GetCurrentDirectory(), 
                                "MyStaticFiles", "images", "banner1.svg");
    
        return PhysicalFile(file, "image/svg+xml");
    }

    三.Enable directory browsing(允许目录浏览)

    目录浏览允许你的web应用上的用户看见一个目录列表,和指定目录里的文件

    目录浏览因为安全原因默认是被禁用的。可以在Startup.Configure方法中调用UseDirectoryBrowser方法来允许目录浏览

    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticFiles(); // For the wwwroot folder
    
        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
            RequestPath = "/MyImages"
        });
    
        app.UseDirectoryBrowser(new DirectoryBrowserOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
            RequestPath = "/MyImages"
        });
    }

    通过在Startup.ConfigureServices中调用AddDirectoryBrowser方法来添加必要的服务:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDirectoryBrowser();
    }

    上面的代码允许 wwwroot/images目录下的目录浏览通过 http://<server_address>/MyImages

    使用这个链接来到达每个文件和目录:

    允许目录浏览的一些安全风险,可以看 Considerations

    注意下面示例中的两个UseStaticFiles的调用。

    第一个调用允许wwwroot文件夹提供静态文件。

    第二个调用允许wwwroot/images文件夹使用目录浏览,通过http://<server_address>/MyImages :

    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticFiles(); // For the wwwroot folder
    
        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
            RequestPath = "/MyImages"
        });
    
        app.UseDirectoryBrowser(new DirectoryBrowserOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
            RequestPath = "/MyImages"
        });
    }

    四.Serve a default document(提供一个默认文档)

    当访问你的网站时,设置一个默认的home page页面提供给浏览者一个合乎逻辑的起始页(默认页)(starting point)

    要提供一个默认的不需要用户详细修饰的URI的页面,需要在Startup.Configure中调用UseDefaultFiles方法

    public void Configure(IApplicationBuilder app)
    {
        app.UseDefaultFiles();
        app.UseStaticFiles();
    }

    重点:UseDefaultFiles 必须在UseStaticFiles之前被调用来提供默认文件。UseDefaultFiles是一个URL重写器,它不会真正提供文件服务。允许Static File Middleware通过UseStaticFiles来提供服务。

    使用UseDefaultFiles,请求一个文件夹搜索:

    • default.htm
    • default.html
    • index.htm
    • index.html

    列表中第一个被找到的文件会提供服务,好像请求是被详细修饰一样。

    下面的代码改变默认文件名为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);

    考虑下面的目录层级:

    下面的代码允许MyStaticFiles中的静态文件,默认文件和目录浏览:

    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticFiles(); // For the wwwroot folder
    
        app.UseFileServer(new FileServerOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
            RequestPath = "/StaticFiles",
            EnableDirectoryBrowsing = true
        });
    }

    当EnableDirectoryBrowsing属性值是true时,AddDirectoryBrowser必须被调用

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDirectoryBrowser();
    }

    使用文件层级和之前的代码,URLs解析如下:

    如果在MyStaticFiles目录中,没有默认名称的文件存在,http://<server_address>/StaticFiles

    返回目录列表中被点击的链接:

    六.FileExtensionContentTypeProvider

    FileExtensionContentTypeProvider类包含一个映射属性,这个映射属性提供一个file extensions 到MIME content types 的映射。下面的代码中,几个文件扩展(file extensions)被注册为已知的MIME types。 .rtf extension被替换了,并且 .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 = "/MyImages",
            ContentTypeProvider = provider
        });
    
        app.UseDirectoryBrowser(new DirectoryBrowserOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
            RequestPath = "/MyImages"
        });
    }

    更多:MIME content types 

    七.Non-standard content types(非标准类型)

    Static File Middleware 理解几乎400个已知的文件类型(file content types).

    如果用户请求一个未知的文件类型,Static File Middleware 会传递这个请求到管道上的下一个中间件。

    如果没有中间件可以处理这个请求,一个404 Not Found 响应会被返回。

    如果目录浏览被允许,在目录列表中,一个到这个文件的链接会被展示。

    下面的代码允许提供未知的类型,并且渲染未知的文件为一个图片:

    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticFiles(new StaticFileOptions
        {
            ServeUnknownFileTypes = true,
            DefaultContentType = "image/png"
        });
    }

    使用上面的代码,一个对未知文件类型的请求会作为一个图片返回。

    警告:允许ServeUnknownFileTypes是有安全风险的。它默认是被禁用的,并且这种用法不推荐使用。FileExtensionContentTypeProvider提供一个更安全的可选的方式来提供带有non-standard extensions扩展的文件。

    Considerations(考虑)

    • 使用UseDirectoryBrowser和UseStaticFiles来暴露内容的URLs是适合于大小写敏感并且在文件系统下有字符限制。例如,Windows是大小写敏感的,macOSLinux不是。
    • ASP.NET Core 应用部署在IIS上,使用ASP.NET Core Module 来发送所有的请求到应用,包括静态文件请求。IIS静态文件处理器(IIS static file handler)没有使用。它没有机会处理请求在它们被这个模块处理之前。
    • 在IIS Manager中移除IIS static file handler的步骤,在服务器或者网站层次:
      1. 导航到Modules功能
      2. 选择列表中的StaticFileModule
      3. 点击删除

    警告:如果IIS文件处理器被允许并且ASP.NET Core Module没有被正确配置,静态文件会提供服务。这会发生,例如,如果web.config文件没有被部署。

    • 存放代码文件(包括.cs.cshtml)在项目的web root的外面。应用的客户端内容和服务端代码在逻辑上应该被分开建立,(app’s client-side content and server-based code).这可以预防服务端代码被泄露。

    地址:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-2.2

  • 相关阅读:
    [Effective JavaScript 笔记]第47条:绝不要在Object.prototype中增加可枚举的属性
    [Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合
    [Effective JavaScript 笔记]第45条:使用hasOwnProperty方法以避免原型污染
    [Effective JavaScript 笔记]第44条:使用null原型以防止原型污染
    redhat下配置SEED DVS6446开发环境3
    redhat下配置SEED DVS6446开发环境2
    redhat下配置SEED DVS6446开发环境1
    关于[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] 的解释
    SQL2008附加数据库报错
    结构体与类
  • 原文地址:https://www.cnblogs.com/Vincent-yuan/p/11247511.html
Copyright © 2011-2022 走看看