ASP.NET Core 中的静态文件
静态文件(如 HTML、CSS、图像和 JavaScript)是 ASP.NET Core 应用直接提供给客户端的资产。 需要进行一些配置才能提供这些文件。
提供静态文件
静态文件存储在项目的 Web 根目录中。 默认目录是 <content_root>/wwwroot,但可通过 UseWebRoot 方法更改目录。 有关详细信息,请参阅内容根目录和 Web 根目录。
应用的 Web 主机必须识别内容根目录。
采用 WebHost.CreateDefaultBuilder 方法可将内容根目录设置为当前目录:
C#
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 根目录的相关路径访问静态文件。 例如,Web 应用程序项目模板包含 wwwroot 文件夹中的多个文件夹:
- wwwrootcssimagesjs
用于访问 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 元包将包括此包。
配置提供静态文件的中间件。
提供 Web 根目录内的文件
调用 Startup.Configure 中的 UseStaticFiles 方法:
C#
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
}
无参数 UseStaticFiles 方法重载将 Web 根目录中的文件标记为可用。 以下标记引用 wwwroot/images/banner1.svg:
CSHTML
<img src="~/images/banner1.svg" alt="ASP.NET" class="img-responsive" />
在上面的代码中,波形符 ~/ 指向 Web 根目录。 有关详细信息,请参阅 Web 根目录。
提供 Web 根目录外的文件
考虑一个目录层次结构,其中要提供的静态文件位于 Web 根目录之外:
- wwwrootcssimagesjs
- MyStaticFilesimagesbanner1.svg
按如下方式配置静态文件中间件后,请求可访问 banner1.svg 文件:
C#
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:
CSHTML
<img src="~/StaticFiles/images/banner1.svg" alt="ASP.NET" class="img-responsive" />
设置 HTTP 响应标头
StaticFileOptions 对象可用于设置 HTTP 响应标头。 除配置从 Web 根目录提供静态文件外,以下代码还设置 Cache-Control 标头:
C#
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 秒):
静态文件授权
静态文件中间件不提供授权检查。 可公开访问由静态文件中间件提供的任何文件,包括 wwwroot 下的文件。 根据授权提供文件:
- 将文件存储在 wwwroot 和静态文件中间件可访问的任何目录之外。
- 通过有授权的操作方法提供文件。 返回 FileResult 对象:C#复制[Authorize] public IActionResult BannerImage() { var file = Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles", "images", "banner1.svg"); return PhysicalFile(file, "image/svg+xml"); }
启用目录浏览
通过目录浏览,Web 应用的用户可查看目录列表和指定目录中的文件。 出于安全考虑,目录浏览默认处于禁用状态(请参阅注意事项)。 调用 Startup.Configure 中的 UseDirectoryBrowser 方法来启用目录浏览:
C#
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 方法来添加所需服务:
C#
public void ConfigureServices(IServiceCollection services)
{
services.AddDirectoryBrowser();
}
上述代码允许使用 URL http://<server_address>/MyImages 浏览 wwwroot/images 文件夹的目录,并链接到每个文件和文件夹:
有关启用浏览时的安全风险,请参阅注意事项。
请注意以下示例中的两个 UseStaticFiles 调用。 第一个调用提供 wwwroot 文件夹中的静态文件。第二个调用使用 URL http://<server_address>/MyImages 浏览 wwwroot/images 文件夹的目录:
C#
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 方法:
C#
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:
C#
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 的功能。
以下代码提供静态文件和默认文件。 未启用目录浏览。
C#
app.UseFileServer();
以下代码通过启用目录浏览基于无参数重载进行构建:
C#
app.UseFileServer(enableDirectoryBrowsing: true);
考虑以下目录层次结构:
- wwwrootcssimagesjs
- MyStaticFilesimagesbanner1.svgdefault.html
以下代码启用静态文件、默认文件和及 MyStaticFiles 的目录浏览:
C#
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:
C#
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 返回包含可单击链接的目录列表:
备注
UseDefaultFiles 和 UseDirectoryBrowser 使用不带尾部反斜杠的 URL http://<server_address>/StaticFiles 触发客户端并重定向到 http://<server_address>/StaticFiles/。 注意添加尾部反斜杠。 无尾部反斜杠,文档中的相对 URL 被视为无效。
FileExtensionContentTypeProvider
FileExtensionContentTypeProvider 类包含 Mappings 属性,用作文件扩展名到 MIME 内容类型的映射。 在以下示例中,多个文件扩展名注册到了已知的 MIME 类型。 替换了 .rtf 扩展名,删除了 .mp4。
C#
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 未找到”响应。 如果启用了目录浏览,则在目录列表中会显示该文件的链接。
以下代码提供未知类型,并以图像形式呈现未知文件:
C#
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "image/png"
});
}
使用前面的代码,请求的文件含未知内容类型时,以图像形式返回请求。
警告
启用 ServeUnknownFileTypes 存在安全风险。 它默认处于禁用状态,不建议使用。FileExtensionContentTypeProvider 提供了更安全的替代方法来提供含非标准扩展名的文件。
注意事项
警告
UseDirectoryBrowser 和 UseStaticFiles 可能会泄漏机密。 强烈建议在生产中禁用目录浏览。请仔细查看 UseStaticFiles 或 UseDirectoryBrowser 启用了哪些目录。 整个目录及其子目录均可公开访问。 将适合公开的文件存储在专用目录中,如 <content_root>/wwwroot。 将这些文件与 MVC 视图、Razor 页面(仅限 2.x)和配置文件等分开
- 使用 UseDirectoryBrowser 和 UseStaticFiles 公开的内容的 URL 受大小写和基础文件系统字符限制的影响。 例如,Windows 不区分大小写 — macOS 和 Linux 却要区分。
- 托管于 IIS 中的 ASP.NET Core 应用使用 ASP.NET Core 模块将所有请求转发到应用,包括静态文件请求。 未使用 IIS 静态文件处理程序。 在模块处理请求前,处理程序没有机会处理请求。
- 在 IIS Manager 中完成以下步骤,删除服务器或网站级别的 IIS 静态文件处理程序:转到“模块”功能。在列表中选择 StaticFileModule。单击“操作”侧栏中的“删除”。
警告
如果启用了 IIS 静态文件处理程序且 ASP.NET Core 模块配置不正确,则会提供静态文件。 例如,如果未部署 web.config 文件,则会发生这种情况。
- 将代码文件(包括 .cs 和 .cshtml )放在应用项目的 Web 根目录之外。 这样就在应用的客户端内容和基于服务器的代码间创建了逻辑分隔。 可以防止服务器端代码泄漏。