zoukankan      html  css  js  c++  java
  • ASP.NET Core 中的静态文件(微软文档)

    默认情况下,静态文件(如 HTML、CSS、图像和 JavaScript)是 ASP.NET Core 应用直接提供给客户端的资产。

    查看或下载示例代码如何下载

    提供静态文件

    静态文件存储在项目的 Web 根目录中。 默认目录为 {content root}/wwwroot,但可通过 UseWebRoot 方法更改目录。 有关详细信息,请参阅内容根目录和 Web 根目录

    采用 CreateDefaultBuilder 方法可将内容根目录设置为当前目录:

    C#
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
    
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
    

    上述代码是使用 Web 应用程序模板创建的。

    可通过 Web 根目录的相关路径访问静态文件。 例如,Web 应用程序项目模板包含 wwwroot 文件夹中的多个文件夹:

    • wwwroot
      • css
      • js
      • lib

    请考虑创建 wwwroot/images 文件夹,并添加 wwwroot/images/MyImage 文件。 用于访问 images 文件夹中的文件的 URI 格式为 https://<hostname>/images/<image_file_name>。 例如,https://localhost:5001/images/MyImage.jpg

    在 Web 根目录中提供文件

    默认 Web 应用模板在 Startup.Configure 中调用 UseStaticFiles 方法,这将允许提供静态文件:

    C#
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
    

    无参数 UseStaticFiles 方法重载将 Web 根目录中的文件标记为可用。 以下标记引用 wwwroot/images/MyImage.jpg:

    HTML
    <img src="~/images/MyImage.jpg" class="img" alt="My image" />
    

    在上面的代码中,波形符 ~/ 指向 Web 根目录

    提供 Web 根目录外的文件

    考虑一个目录层次结构,其中要提供的静态文件位于 Web 根目录之外:

    • wwwroot
      • css
      • images
      • js
    • MyStaticFiles
      • images
        • red-rose.jpg

    按如下方式配置静态文件中间件后,请求可访问 red-rose.jpg 文件:

    C#
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        // using Microsoft.Extensions.FileProviders;
        // using System.IO;
        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(env.ContentRootPath, "MyStaticFiles")),
            RequestPath = "/StaticFiles"
        });
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
    

    在前面的代码中,MyStaticFiles 目录层次结构通过 StaticFiles URI 段公开 。 对 https://<hostname>/StaticFiles/images/red-rose.jpg 的请求将提供 red-rose.jpg 文件。

    以下标记引用 MyStaticFiles/images/red-rose.jpg:

    HTML
    <img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
    

    设置 HTTP 响应标头

    StaticFileOptions 对象可用于设置 HTTP 响应标头。 除配置从 Web 根目录提供静态文件外,以下代码还设置 Cache-Control 标头:

    C#
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        const string cacheMaxAge = "604800";
        app.UseStaticFiles(new StaticFileOptions
        {
            OnPrepareResponse = ctx =>
            {
                // using Microsoft.AspNetCore.Http;
                ctx.Context.Response.Headers.Append(
                     "Cache-Control", $"public, max-age={cacheMaxAge}");
            }
        });
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
    

    静态文件可在 600 秒内公开缓存:

    已添加显示 Cache-Control 标头的响应头

    静态文件授权

    ASP.NET Core 模板在调用 UseAuthorization 之前调用 UseStaticFiles。 大多数应用都遵循此模式。 如果在授权中间件之前调用静态文件中间件:

    • 不会对静态文件执行任何授权检查。
    • 由静态文件中间件提供的静态文件(例如 wwwroot 下的文件)可公开访问。

    根据授权提供静态文件:

    • 将它们存储在 wwwroot 之外。
    • 调用 UseAuthorization 之后调用 UseStaticFiles,以指定路径。
    • 设置回退授权策略
    C#
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        // wwwroot css, JavaScript, and images don't require authentication.
        app.UseStaticFiles();   
    
        app.UseRouting();
    
        app.UseAuthentication();
        app.UseAuthorization();
    
        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(
                         Path.Combine(env.ContentRootPath, "MyStaticFiles")),
            RequestPath = "/StaticFiles"
        });
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
    
    C#
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));
            services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<ApplicationDbContext>();
    
            services.AddRazorPages();
    
            services.AddAuthorization(options =>
            {
                options.FallbackPolicy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
            });
        }
    
        // Remaining code ommitted for brevity.
    

    在前面的代码中,回退授权策略要求所有用户进行身份验证。 用于指定其自己的授权要求的终结点(如控制器、Razor Pages 等)不使用回退授权策略。 例如,具有 [AllowAnonymous] 或 [Authorize(PolicyName="MyPolicy")] 的 Razor Pages、控制器或操作方法使用应用的授权属性,而不是回退授权策略。

    RequireAuthenticatedUser 将 DenyAnonymousAuthorizationRequirement 添加到当前实例,这将强制对当前用户进行身份验证。

    wwwroot 下的静态资产是可公开访问的,因为在 UseAuthentication 之前会调用默认静态文件中间件 (app.UseStaticFiles();)。 MyStaticFiles 文件夹中的静态资产需要身份验证。 示例代码对此进行了演示。

    还有一种根据授权提供文件的方法是:

    • 将文件存储在 wwwroot 和静态文件中间件可访问的任何目录之外。
    • 通过应用授权的操作方法为其提供服务,并返回 FileResult 对象:
    C#
    [Authorize]
    public IActionResult BannerImage()
    {
        var filePath = Path.Combine(
            _env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");
    
        return PhysicalFile(filePath, "image/jpeg");
    }
    

    目录浏览

    目录浏览允许在指定目录中列出目录。

    出于安全考虑,目录浏览默认处于禁用状态。 有关详细信息,请参阅静态文件的安全注意事项

    通过以下方式启用目录浏览:

    C#
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddDirectoryBrowser();
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        // using Microsoft.Extensions.FileProviders;
        // using System.IO;
        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(env.WebRootPath, "images")),
            RequestPath = "/MyImages"
        });
    
        app.UseDirectoryBrowser(new DirectoryBrowserOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(env.WebRootPath, "images")),
            RequestPath = "/MyImages"
        });
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
    

    上述代码允许使用 URL https://<hostname>/MyImages 浏览 wwwroot/images 文件夹的目录,并链接到每个文件和文件夹:

    目录浏览

    提供默认文档

    设置默认页面为访问者提供网站的起点。 若要从 wwwroot 提供默认文件,而不要求请求 URL 包含文件名,请调用 UseDefaultFiles 方法:

    C#
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        app.UseDefaultFiles();
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
    

    要提供默认文件,必须在 UseStaticFiles 前调用 UseDefaultFiles。 UseDefaultFiles 是不提供文件的 URL 重写工具。

    使用 UseDefaultFiles 请求对 wwwroot 中的文件夹搜索:

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

    如同请求包含了文件名一样,提供从列表中找到的第一个文件。 浏览器 URL 继续反映请求的 URI。

    以下代码将默认文件名更改为 mydefault.html:

    C#
    var options = new DefaultFilesOptions();
    options.DefaultFileNames.Clear();
    options.DefaultFileNames.Add("mydefault.html");
    app.UseDefaultFiles(options);
    app.UseStaticFiles();
    

    以下代码通过上述代码演示了 Startup.Configure

    C#
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        var options = new DefaultFilesOptions();
        options.DefaultFileNames.Clear();
        options.DefaultFileNames.Add("mydefault.html");
        app.UseDefaultFiles(options);
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
    

    默认文档的 UseFileServer

    UseFileServer 结合了 UseStaticFilesUseDefaultFiles 和 UseDirectoryBrowser(可选)的功能。

    调用 app.UseFileServer 以提供静态文件和默认文件。 未启用目录浏览。 以下代码通过 UseFileServer 演示了 Startup.Configure

    C#
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        app.UseFileServer();
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
    

    以下代码提供静态文件、默认文件和目录浏览:

    C#
    app.UseFileServer(enableDirectoryBrowsing: true);
    

    以下代码通过上述代码演示了 Startup.Configure

    C#
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        app.UseFileServer(enableDirectoryBrowsing: true);
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
    

    考虑以下目录层次结构:

    • wwwroot
      • css
      • images
      • js
    • MyStaticFiles
      • images
        • MyImage.jpg
      • default.html

    以下代码提供静态文件、默认文件和 MyStaticFiles 的目录浏览:

    C#
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddDirectoryBrowser();
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        app.UseStaticFiles(); // For the wwwroot folder.
    
        // using Microsoft.Extensions.FileProviders;
        // using System.IO;
        app.UseFileServer(new FileServerOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(env.ContentRootPath, "MyStaticFiles")),
            RequestPath = "/StaticFiles",
            EnableDirectoryBrowsing = true
        });
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
    

    必须在 EnableDirectoryBrowsing 属性值为 true 时调用 AddDirectoryBrowser

    使用文件层次结构和前面的代码,URL 解析如下:

    表 1
    URI响应
    https://<hostname>/StaticFiles/images/MyImage.jpg MyStaticFiles/images/MyImage.jpg
    https://<hostname>/StaticFiles MyStaticFiles/default.html

    如果 MyStaticFiles 目录中不存在默认命名文件,则 https://<hostname>/StaticFiles 返回包含可单击链接的目录列表:

    静态文件列表

    UseDefaultFiles 和 UseDirectoryBrowser 执行从不带尾部 / 的目标 URI 到带尾部 / 的目标 URI 的客户端重定向。 例如,从 https://<hostname>/StaticFiles 到 https://<hostname>/StaticFiles/。 如果没有尾部斜杠 (/),StaticFiles 目录中的相对 URL 无效。

    FileExtensionContentTypeProvider

    FileExtensionContentTypeProvider 类包含 Mappings 属性,用作文件扩展名到 MIME 内容类型的映射。 在以下示例中,多个文件扩展名映射到了已知的 MIME 类型。 替换了 .rtf 扩展名,删除了 .mp4 :

    C#
    // using Microsoft.AspNetCore.StaticFiles;
    // using Microsoft.Extensions.FileProviders;
    // using System.IO;
    
    // 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(env.WebRootPath, "images")),
        RequestPath = "/MyImages",
        ContentTypeProvider = provider
    });
    
    app.UseDirectoryBrowser(new DirectoryBrowserOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(env.WebRootPath, "images")),
        RequestPath = "/MyImages"
    });
    

    以下代码通过上述代码演示了 Startup.Configure

    C#
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        // using Microsoft.AspNetCore.StaticFiles;
        // using Microsoft.Extensions.FileProviders;
        // using System.IO;
    
        // 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(env.WebRootPath, "images")),
            RequestPath = "/MyImages",
            ContentTypeProvider = provider
        });
    
        app.UseDirectoryBrowser(new DirectoryBrowserOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(env.WebRootPath, "images")),
            RequestPath = "/MyImages"
        });
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
    

    请参阅 MIME 内容类型

    非标准内容类型

    静态文件中间件可理解近 400 种已知文件内容类型。 如果用户请求文件类型未知的文件,则静态文件中间件将请求传递给管道中的下一个中间件。 如果没有中间件处理请求,则返回“404 未找到”响应。 如果启用了目录浏览,则在目录列表中会显示该文件的链接。

    以下代码提供未知类型,并以图像形式呈现未知文件:

    C#
    app.UseStaticFiles(new StaticFileOptions
    {
        ServeUnknownFileTypes = true,
        DefaultContentType = "image/png"
    });
    

    以下代码通过上述代码演示了 Startup.Configure

    C#
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        app.UseStaticFiles(new StaticFileOptions
        {
            ServeUnknownFileTypes = true,
            DefaultContentType = "image/png"
        });
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
    

    使用前面的代码,请求的文件含未知内容类型时,以图像形式返回请求。

     警告

    启用 ServeUnknownFileTypes 会形成安全隐患。 它默认处于禁用状态,不建议使用。 FileExtensionContentTypeProvider 提供了更安全的替代方法来提供含非标准扩展名的文件。

    从多个位置提供文件

    UseStaticFiles 和 UseFileServer 默认为指向 wwwroot 的文件提供程序。 可使用其他文件提供程序提供 UseStaticFiles 和 UseFileServer 的其他实例,从多个位置提供文件。 有关详细信息,请参阅此 GitHub 问题

    静态文件的安全注意事项

     警告

    UseDirectoryBrowser 和 UseStaticFiles 可能会泄漏机密。 强烈建议在生产中禁用目录浏览。 请仔细查看 UseStaticFiles 或 UseDirectoryBrowser 启用了哪些目录。 整个目录及其子目录均可公开访问。 将适合公开的文件存储在专用目录中,如 <content_root>/wwwroot。 将这些文件与 MVC 视图、Razor Pages 和配置文件等分开。

    • 使用 UseDirectoryBrowser 和 UseStaticFiles 公开的内容的 URL 受大小写和基础文件系统字符限制的影响。 例如,Windows 不区分大小写,但 macOS 和 Linux 区分大小写。

    • 托管于 IIS 中的 ASP.NET Core 应用使用 ASP.NET Core 模块将所有请求转发到应用,包括静态文件请求。 不使用 IIS 静态文件处理程序,并且没有机会处理请求。

    • 在 IIS Manager 中完成以下步骤,删除服务器或网站级别的 IIS 静态文件处理程序:

      1. 转到“模块”功能。
      2. 在列表中选择 StaticFileModule。
      3. 单击“操作”侧栏中的“删除” 。

     警告

    如果启用了 IIS 静态文件处理程序且 ASP.NET Core 模块配置不正确,则会提供静态文件。 例如,如果未部署 web.config 文件,则会发生这种情况。

    • 将代码文件(包括 .cs 和 .cshtml)放在应用项目的 Web 根目录之外 。 这样就在应用的客户端内容和基于服务器的代码间创建了逻辑分隔。 可以防止服务器端代码泄漏。
  • 相关阅读:
    27. Remove Element
    26. Remove Duplicates from Sorted Array
    643. Maximum Average Subarray I
    674. Longest Continuous Increasing Subsequence
    1. Two Sum
    217. Contains Duplicate
    448. Find All Numbers Disappeared in an Array
    566. Reshape the Matrix
    628. Maximum Product of Three Numbers
    UVa 1349 Optimal Bus Route Design (最佳完美匹配)
  • 原文地址:https://www.cnblogs.com/lzjsky/p/15784086.html
Copyright © 2011-2022 走看看