Nguon: Microsoft Learn · .NET 8.0

File tĩnh (Static files) trong ASP.NET Core

Nguồn: Static files in ASP.NET Core

Static files (file tĩnh), còn được gọi là static assets (tài nguyên tĩnh), là các file trong ứng dụng ASP.NET Core không được tạo ra động. Thay vào đó, chúng được phục vụ trực tiếp cho client theo yêu cầu, chẳng hạn như các file HTML, CSS, hình ảnh và JavaScript.

Để bật xử lý static file trong ASP.NET Core (phiên bản 8.0), gọi UseStaticFiles.

Theo mặc định, static file được lưu trong thư mục web root của project. Thư mục mặc định là {CONTENT ROOT}/wwwroot, trong đó {CONTENT ROOT}content root của ứng dụng. Chỉ các file trong thư mục wwwroot mới có thể truy cập được, vì vậy bạn không cần lo lắng về phần còn lại của code.

Khi chạy, static web asset được trả về bởi Static File Middleware (phần mềm trung gian file tĩnh) khi được yêu cầu cùng với các header thay đổi tài sản và loại nội dung. Các header ETag, Last-ModifiedContent-Type được đặt.

Static File Middleware cho phép phục vụ static file và được sử dụng bởi ứng dụng khi UseStaticFiles được gọi trong pipeline xử lý request của ứng dụng. Các file được phục vụ từ đường dẫn được chỉ định trong IWebHostEnvironment.WebRootPath hoặc WebRootFileProvider, mặc định là thư mục web root, thường là wwwroot.

Bạn cũng có thể phục vụ static web asset từ các project và package được tham chiếu.

Thay đổi thư mục web root

Sử dụng phương thức UseWebRoot nếu bạn muốn thay đổi web root. Để biết thêm thông tin, xem ASP.NET Core fundamentals overview.

Ngăn publish các file trong wwwroot bằng cách sử dụng phần tử <Content> project item trong file project. Ví dụ sau ngăn publish nội dung trong wwwroot/local và các thư mục con:

xml
<ItemGroup>
  <Content Update="wwwroot\local\**\*.*" CopyToPublishDirectory="Never" />
</ItemGroup>

Phương thức CreateBuilder đặt content root thành thư mục hiện tại:

csharp
var builder = WebApplication.CreateBuilder(args);

Trong request processing pipeline sau khi gọi UseHttpsRedirection, gọi UseStaticFiles để cho phép phục vụ static file từ web root của ứng dụng:

csharp
app.UseStaticFiles();

Static file có thể truy cập được thông qua một đường dẫn tương đối so với web root.

Để truy cập hình ảnh tại wwwroot/images/favicon.png:

Trong Razor Pages và ứng dụng MVC, ký tự tilde ~ trỏ đến web root. Trong ví dụ sau, ~/images/favicon.png tải hình ảnh từ thư mục wwwroot/images:

cshtml
<link rel="icon" type="image/png" href="~/images/favicon.png" />

Static files trong môi trường không phải Development

Khi chạy ứng dụng cục bộ, static web asset chỉ được bật trong môi trường Development. Để bật static file cho các môi trường khác ngoài Development trong quá trình phát triển và kiểm tra cục bộ (ví dụ: môi trường Staging), gọi UseStaticWebAssets trên WebApplicationBuilder:

Gọi UseStaticWebAssets cho đúng môi trường để tránh kích hoạt tính năng trong production, vì nó phục vụ file từ các vị trí riêng biệt trên đĩa khác với từ project.

csharp
if (builder.Environment.IsStaging())
{
    builder.WebHost.UseStaticWebAssets();
}

Phục vụ file ngoài thư mục web root qua UseStaticFiles

Xét cấu trúc thư mục sau với static file nằm ngoài web root của ứng dụng trong thư mục ExtraStaticFiles:

Một request có thể truy cập red-rose.jpg bằng cách cấu hình một instance mới của Static File Middleware:

csharp
using Microsoft.Extensions.FileProviders;

Trong request processing pipeline sau khi gọi UseStaticFiles:

csharp
app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(builder.Environment.ContentRootPath, "ExtraStaticFiles")),
    RequestPath = "/static-files"
});

Trong đoạn code trên, cấu trúc thư mục ExtraStaticFiles được công khai thông qua đoạn URL static-files. Một request tới https://{HOST}/StaticFiles/images/red-rose.jpg sẽ phục vụ file red-rose.jpg.

Phục vụ file từ nhiều vị trí

Gọi UseStaticFiles hai lần để phục vụ file từ cả wwwrootExtraStaticFiles:

csharp
app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(builder.Environment.ContentRootPath, "ExtraStaticFiles"))
});

Cập nhật WebRootFileProvider để bao gồm thư mục ExtraStaticFiles bằng cách sử dụng CompositeFileProvider. Điều này cho phép Image Tag Helper áp dụng phiên bản cho hình ảnh trong thư mục ExtraStaticFiles:

csharp
using Microsoft.Extensions.FileProviders;

var webRootProvider = new PhysicalFileProvider(builder.Environment.WebRootPath);
var newPathProvider = new PhysicalFileProvider(
    Path.Combine(builder.Environment.ContentRootPath, "ExtraStaticFiles"));

var compositeProvider = new CompositeFileProvider(webRootProvider, newPathProvider);

app.Environment.WebRootFileProvider = compositeProvider;

Đặt HTTP response headers

Sử dụng StaticFileOptions để đặt HTTP response header. Ngoài việc cấu hình Static File Middleware để phục vụ static file, đoạn code sau đặt header Cache-Control thành 604.800 giây (một tuần):

csharp
using Microsoft.AspNetCore.Http;

app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = ctx =>
    {
        ctx.Context.Response.Headers.Append(
            "Cache-Control", "public, max-age=604800");
    }
});

Phân quyền file tĩnh (Static file authorization)

Khi ứng dụng áp dụng fallback authorization policy, yêu cầu xác thực cho tất cả các request không chỉ định rõ authorization policy, bao gồm cả request cho static file sau khi Authorization Middleware xử lý request. Các template ASP.NET Core cho phép truy cập ẩn danh vào static file bằng cách gọi UseStaticFiles trước khi gọi UseAuthorization. Khi Static File Middleware được gọi trước authorization middleware:

Để phục vụ static file dựa trên authorization:

csharp
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.FileProviders;

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
});

// ...

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(builder.Environment.ContentRootPath, "SecureStaticFiles")),
    RequestPath = "/static-files"
});

Directory browsing (Duyệt thư mục)

Directory browsing cho phép liệt kê thư mục trong các thư mục được chỉ định.

Directory browsing bị tắt theo mặc định vì lý do bảo mật.

Bật directory browsing với các API sau:

csharp
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;

builder.Services.AddDirectoryBrowser();

// ...

var fileProvider = new PhysicalFileProvider(
    Path.Combine(builder.Environment.WebRootPath, "images"));
var requestPath = "/DirectoryImages";

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = fileProvider,
    RequestPath = requestPath
});

app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
    FileProvider = fileProvider,
    RequestPath = requestPath
});

Đoạn code trên cho phép duyệt thư mục wwwroot/images bằng URL https://{HOST}/DirectoryImages với các liên kết đến từng file và thư mục.

Phục vụ tài liệu mặc định (Default documents)

Đặt trang mặc định cung cấp cho khách truy cập một điểm khởi đầu trên trang web. Để phục vụ một file mặc định từ wwwroot mà không yêu cầu URL request phải bao gồm tên file, gọi phương thức UseDefaultFiles:

csharp
app.UseDefaultFiles();

Với UseDefaultFiles, các request đến một thư mục trong wwwroot sẽ tìm kiếm:

File đầu tiên tìm thấy trong danh sách sẽ được phục vụ như thể request đã bao gồm tên file.

Đoạn code sau thay đổi tên file mặc định thành default-document.html:

csharp
var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("default-document.html");
app.UseDefaultFiles(options);

Kết hợp static files, tài liệu mặc định và duyệt thư mục

UseFileServer kết hợp chức năng của UseStaticFiles, UseDefaultFiles và tùy chọn UseDirectoryBrowser.

Gọi UseFileServer để bật phục vụ static file và file mặc định:

csharp
app.UseFileServer();

Đoạn code sau bật phục vụ static file, file mặc định và directory browsing:

csharp
builder.Services.AddDirectoryBrowser();

// ...

app.UseFileServer(enableDirectoryBrowsing: true);

Map file extensions sang MIME types

Sử dụng FileExtensionContentTypeProvider.Mappings để thêm hoặc sửa đổi ánh xạ từ phần mở rộng file sang MIME content type. Trong ví dụ sau, một số phần mở rộng file được ánh xạ sang các MIME type đã biết. Phần mở rộng .rtf được thay thế và .mp4 bị xóa:

csharp
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;

// ...

// Thiết lập content type tùy chỉnh - liên kết phần mở rộng file với MIME type
var provider = new FileExtensionContentTypeProvider();
// Thêm ánh xạ mới
provider.Mappings[".myapp"] = "application/x-msdownload";
provider.Mappings[".htm3"] = "text/html";
provider.Mappings[".image"] = "image/png";
// Thay thế ánh xạ hiện có
provider.Mappings[".rtf"] = "application/x-msdownload";
// Xóa video MP4
provider.Mappings.Remove(".mp4");

app.UseStaticFiles(new StaticFileOptions
{
    ContentTypeProvider = provider
});

Non-standard content types (Loại nội dung không tiêu chuẩn)

Static File Middleware hiểu gần 400 loại nội dung file đã biết. Nếu người dùng yêu cầu một file với loại file không rõ, Static File Middleware chuyển request đến middleware tiếp theo trong pipeline. Nếu không có middleware nào xử lý request, phản hồi 404 Not Found được trả về.

Đoạn code sau bật phục vụ các content type không rõ và hiển thị file không rõ như một hình ảnh:

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

Bật ServeUnknownFileTypes là một rủi ro bảo mật. Nó bị tắt theo mặc định và không khuyến khích sử dụng. Ánh xạ phần mở rộng file sang MIME type cung cấp một giải pháp thay thế an toàn hơn để phục vụ file với các phần mở rộng không tiêu chuẩn.

Các cân nhắc bảo mật cho static file

UseDirectoryBrowserUseStaticFiles có thể rò rỉ thông tin bí mật. Rất khuyến nghị tắt directory browsing trong production. Xem xét cẩn thận các thư mục nào được bật thông qua UseStaticFiles hoặc UseDirectoryBrowser. Toàn bộ thư mục và các thư mục con của nó sẽ có thể truy cập công khai. Lưu trữ các file phù hợp để phục vụ công khai trong một thư mục chuyên dụng, chẳng hạn như <content_root>/wwwroot. Tách các file này khỏi các MVC view, Razor Pages, file cấu hình, v.v.