静态文件

ASP.NET Core 中的静态文件

作者:Rick AndersonScott Addie

静态文件(如 HTML、CSS、图像和 JavaScript)是 ASP.NET Core 应用直接提供给客户端的资产。 需要进行一些配置才能提供这些文件。

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

提供静态文件

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

应用的 Web 主机必须识别内容根目录。

采用 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>();
}

调用 Program.Main 中的 UseContentRoot 将内容根目录设为当前目录:

public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .UseApplicationInsights()
            .Build();

        host.Run();
    }        
}

可通过 Web 根目录的相关路径访问静态文件。 例如,Web 应用程序项目模板包含 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 元包将包括此包。

如果以 .NET Framework 为目标,请将 Microsoft.AspNetCore.StaticFiles 包添加到项目。 如果以 .NET Core 为目标,请将 Microsoft.AspNetCore.All 元包加入此包。

Microsoft.AspNetCore.StaticFiles 包添加到项目。

配置提供静态文件的中间件

提供 Web 根目录内的文件

调用 Startup.Configure 中的 UseStaticFiles 方法:

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

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

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

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

提供 Web 根目录外的文件

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

  • wwwroot
    • css
    • images
    • js
  • MyStaticFiles
    • images
      • banner1.svg

按如下方式配置静态文件中间件后,请求可访问 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" />

设置 HTTP 响应标头

StaticFileOptions 对象可用于设置 HTTP 响应标头。 除配置从 Web 根目录提供静态文件外,以下代码还设置 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 秒):

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

静态文件授权

静态文件中间件不提供授权检查。 可公开访问由静态文件中间件提供的任何文件,包括 wwwroot 下的文件。 根据授权提供文件:

  • 将文件存储在 wwwroot 和静态文件中间件可访问的任何目录之外 。

  • 通过有授权的操作方法提供文件。 返回 FileResult 对象:

    [Authorize]
    public IActionResult BannerImage()
    {
        var file = Path.Combine(Directory.GetCurrentDirectory(), 
                                "MyStaticFiles", "images", "banner1.svg");
    
        return PhysicalFile(file, "image/svg+xml");
    }
    

启用目录浏览

通过目录浏览,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();
}

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

目录浏览

有关启用浏览时的安全风险,请参阅注意事项

请注意以下示例中的两个 UseStaticFiles 调用。 第一个调用提供 wwwroot 文件夹中的静态文件 。 第二个调用使用 URL http://<server_address>/MyImages 浏览 wwwroot/images 文件夹的目录 :

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"
    });
}

提供默认文档

设置默认主页为访问者访问网站时提供了逻辑起点。 若要在用户不完全限定 URI 的情况下提供默认页面,请调用 Startup.Configure 中的 UseDefaultFiles 方法:

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

重要

要提供默认文件,必须在 UseStaticFiles 前调用 UseDefaultFiles 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 结合了 UseStaticFilesUseDefaultFilesUseDirectoryBrowser(可选)的功能。

以下代码提供静态文件和默认文件。 未启用目录浏览。

app.UseFileServer();

以下代码通过启用目录浏览基于无参数重载进行构建:

app.UseFileServer(enableDirectoryBrowsing: true);

考虑以下目录层次结构:

  • wwwroot
    • css
    • images
    • js
  • MyStaticFiles
    • images
      • banner1.svg
    • default.html

以下代码启用静态文件、默认文件和及 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();
}

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

URI 响应
http://<server_address>/StaticFiles/images/banner1.svg MyStaticFiles/images/banner1.svg
http://<server_address>/StaticFiles MyStaticFiles/default.html

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

静态文件列表

备注

UseDefaultFilesUseDirectoryBrowser 执行从 http://{SERVER ADDRESS}/StaticFiles(不带尾部斜杠)到 http://{SERVER ADDRESS}/StaticFiles/(带尾部斜杠)的客户端重定向。 如果没有尾部斜杠,StaticFiles 目录中的相对 URL 无效。

FileExtensionContentTypeProvider

FileExtensionContentTypeProvider 类包含 Mappings 属性,用作文件扩展名到 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 = "/MyImages",
        ContentTypeProvider = provider
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
        RequestPath = "/MyImages"
    });
}

请参阅 MIME 内容类型

非标准内容类型

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

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

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

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

警告

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

从多个位置提供文件

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

注意事项

警告

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

  • 使用 UseDirectoryBrowserUseStaticFiles 公开的内容的 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 根目录之外 。 这样就在应用的客户端内容和基于服务器的代码间创建了逻辑分隔。 可以防止服务器端代码泄漏。

其他资源