Udostępnij za pośrednictwem


Pliki statyczne w ASP.NET Core

Uwaga

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zobacz artykuł w wersji .NET 9.

Ostrzeżenie

Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core. Aby zapoznać się z bieżącą wersją, zobacz artykuł w wersji .NET 9.

Ważne

Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.

Aby zapoznać się z bieżącą wersją, zobacz wersję artykułu .NET 9.

Autor: Rick Anderson

Pliki statyczne, takie jak HTML, CSS, images i JavaScript, to zasoby, które ASP.NET Aplikacja Core domyślnie obsługuje bezpośrednio klientom.

Obsługa plików statycznych

Pliki statyczne są przechowywane w katalogu głównym projektu. Domyślny katalog to {content root}/wwwroot, ale można go zmienić za pomocą UseWebRoot metody . Aby uzyskać więcej informacji, zobacz Katalog główny zawartości i Główny katalog Web.

Metoda CreateBuilder ustawia katalog główny zawartości na bieżący katalog:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Pliki statyczne są dostępne za pośrednictwem ścieżki względem katalogu głównego sieci Web. Na przykład szablony projektów aplikacji internetowej zawierają kilka folderów w folderze wwwroot :

  • wwwroot
    • css
    • js
    • lib

Rozważ utworzenie folderu wwwroot/images i dodanie wwwroot/images/MyImage.jpg pliku. Format identyfikatora URI umożliwiający dostęp do pliku w folderze images to https://<hostname>/images/<image_file_name>. Na przykład https://localhost:5001/images/MyImage.jpg

Obsługa plików w katalogu głównym sieci Web

Domyślne szablony aplikacji internetowej wywołują metodę UseStaticFiles w Program.cs, co umożliwia obsługę plików statycznych.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Przeciążenie metody bezparametrowej oznacza pliki w katalogu głównym sieci Web jako udostępniane. Następujące odniesienia do znaczników wwwroot/images/MyImage.jpg:

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

W poprzednim znaczniku znak tyldy ~ wskazuje na katalog główny sieci web.

Serwowanie plików spoza katalogu głównego web

Rozważ hierarchię katalogów, w której pliki statyczne, które mają być obsługiwane, znajdują się poza katalogiem głównym sieci Web:

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

Żądanie może uzyskać dostęp do pliku red-rose.jpg, konfigurując oprogramowanie pośredniczące do obsługi plików statycznych w następujący sposób:

using Microsoft.Extensions.FileProviders;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
           Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
    RequestPath = "/StaticFiles"
});

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

W poprzednim kodzie hierarchia katalogów MyStaticFiles jest uwidoczniona publicznie za pośrednictwem segmentu identyfikatora URI StaticFiles . Żądanie https://<hostname>/StaticFiles/images/red-rose.jpg dotyczy pliku red-rose.jpg.

Następujące odwołania do znaczników MyStaticFiles/images/red-rose.jpg:

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

Aby obsłużyć pliki z wielu lokalizacji, zobacz Obsługa plików z wielu lokalizacji.

Ustawianie nagłówków odpowiedzi HTTP

Obiekt StaticFileOptions może służyć do ustawiania nagłówków odpowiedzi HTTP. Oprócz konfigurowania serwowania plików statycznych z katalogu głównego sieci Web, następujący kod ustawia nagłówek Cache-Control:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

var cacheMaxAgeOneWeek = (60 * 60 * 24 * 7).ToString();
app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = ctx =>
    {
        ctx.Context.Response.Headers.Append(
             "Cache-Control", $"public, max-age={cacheMaxAgeOneWeek}");
    }
});

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Powyższy kod udostępnia pliki statyczne publicznie w lokalnej pamięci podręcznej przez tydzień (604800 sekund).

Autoryzacja pliku statycznego

Szablony ASP.NET Core wywołują UseStaticFiles przed wywołaniem UseAuthorization. Większość aplikacji podąża za tym wzorcem. Gdy oprogramowanie pośredniczące plików statycznych jest wywoływane przed oprogramowaniem pośredniczącym autoryzacji:

  • W plikach statycznych nie są wykonywane kontrole autoryzacji.
  • Pliki statyczne obsługiwane przez middleware do obsługi plików statycznych, takie jak w obszarze wwwroot, są publicznie dostępne.

Aby obsługiwać pliki statyczne na podstawie autoryzacji:

  • Przechowuj je poza elementem wwwroot.
  • Wywołaj metodę UseStaticFiles, określając ścieżkę po wywołaniu metody UseAuthorization.
  • Ustaw zapasową politykę autoryzacji.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using StaticFileAuth.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

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

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
           Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
    RequestPath = "/StaticFiles"
});

app.MapRazorPages();

app.Run();

W poprzednim kodzie zasady autoryzacji rezerwowej wymagają uwierzytelnienia wszystkich użytkowników. Punkty końcowe, takie jak kontrolery, Razor strony itp., które określają własne wymagania dotyczące autoryzacji, nie korzystają z zasad autoryzacji rezerwowej. Na przykład Razor strony, kontrolery lub metody akcji z zastosowanym atrybutem [AllowAnonymous] lub [Authorize(PolicyName="MyPolicy")] używają tego atrybutu zamiast rezerwowej polityki autoryzacji.

RequireAuthenticatedUser dodaje DenyAnonymousAuthorizationRequirement do bieżącego wystąpienia, co wymusza uwierzytelnienie bieżącego użytkownika.

Zasoby statyczne w obszarze wwwroot są publicznie dostępne, ponieważ domyślne oprogramowanie pośredniczące plików statycznych (app.UseStaticFiles();) jest wywoływane przed UseAuthentication. Zasoby statyczne w folderze MyStaticFiles wymagają uwierzytelniania. Przykładowy kod pokazuje to.

Alternatywną metodą udostępniania plików na podstawie autoryzacji jest:

  • Przechowuj je poza wwwroot oraz wszystkimi katalogami, do których ma dostęp oprogramowanie pośredniczące do obsługi plików statycznych.

  • Serwuj je za pomocą metody akcji, do której stosowana jest autoryzacja, i zwracaj obiekt FileResult.

    [Authorize]
    public class BannerImageModel : PageModel
    {
        private readonly IWebHostEnvironment _env;
    
        public BannerImageModel(IWebHostEnvironment env) =>
            _env = env;
    
        public PhysicalFileResult OnGet()
        {
            var filePath = Path.Combine(
                    _env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");
    
            return PhysicalFile(filePath, "image/jpeg");
        }
    }
    

Powyższe podejście wymaga strony lub punktu końcowego dla każdego pliku. Poniższy kod zwraca pliki lub przekazuje pliki dla uwierzytelnionych użytkowników:

app.MapGet("/files/{fileName}",  IResult (string fileName) => 
    {
        var filePath = GetOrCreateFilePath(fileName);

        if (File.Exists(filePath))
        {
            return TypedResults.PhysicalFile(filePath, fileDownloadName: $"{fileName}");
        }

        return TypedResults.NotFound("No file found with the supplied file name");
    })
    .WithName("GetFileByName")
    .RequireAuthorization("AuthenticatedUsers");

// IFormFile uses memory buffer for uploading. For handling large file use streaming instead.
// https://learn.microsoft.com/aspnet/core/mvc/models/file-uploads#upload-large-files-with-streaming
app.MapPost("/files", async (IFormFile file, LinkGenerator linker, HttpContext context) =>
    {
        // Don't rely on the file.FileName as it is only metadata that can be manipulated by the end-user
        // Take a look at the `Utilities.IsFileValid` method that takes an IFormFile and validates its signature within the AllowedFileSignatures
        
        var fileSaveName = Guid.NewGuid().ToString("N") + Path.GetExtension(file.FileName);
        await SaveFileWithCustomFileName(file, fileSaveName);
        
        context.Response.Headers.Append("Location", linker.GetPathByName(context, "GetFileByName", new { fileName = fileSaveName}));
        return TypedResults.Ok("File Uploaded Successfully!");
    })
    .RequireAuthorization("AdminsOnly");

app.Run();

Aby uzyskać pełny przykład, zobacz folder GitHub StaticFileAuth.

Przeglądanie katalogów

Przeglądanie katalogów umożliwia wyświetlanie listy katalogów w określonych katalogach.

Przeglądanie katalogów jest domyślnie wyłączone ze względów bezpieczeństwa. Aby uzyskać więcej informacji, zobacz Zagadnienia dotyczące zabezpieczeń plików statycznych.

Włącz przeglądanie katalogów za pomocą polecenia AddDirectoryBrowser i UseDirectoryBrowser:

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

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddDirectoryBrowser();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

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

// Enable displaying browser links.
app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = fileProvider,
    RequestPath = requestPath
});

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

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Powyższy kod umożliwia przeglądanie katalogów folderu wwwroot/images przy użyciu adresu URL https://<hostname>/MyImages, z linkami do każdego pliku i folderu:

przeglądanie katalogów

AddDirectoryBrowser dodaje usługi wymagane przez oprogramowanie pośredniczące przeglądania katalogów, w tym HtmlEncoder. Te usługi mogą być dodawane przez inne wywołania, takie jak AddRazorPages, ale zalecamy wywołanie, AddDirectoryBrowser aby upewnić się, że usługi są dodawane we wszystkich aplikacjach.

Obsługa dokumentów domyślnych

Ustawienie strony domyślnej zapewnia odwiedzającym punkt początkowy w witrynie. Aby obsłużyć plik domyślny z wwwroot bez potrzeby uwzględniania nazwy pliku w adresie URL żądania, wywołaj metodę UseDefaultFiles.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseDefaultFiles();

app.UseStaticFiles();
app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

UseDefaultFiles musi być wywołana przed UseStaticFiles aby obsłużyć plik domyślny. UseDefaultFiles jest narzędziem do przepisywania adresów URL, które nie dostarcza pliku.

Za pomocą UseDefaultFiles żądania do folderu w wwwroot wyszukują:

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

Pierwszy plik znaleziony na liście jest obsługiwany tak, jakby żądanie zawierało nazwę pliku. Adres URL przeglądarki nadal odzwierciedla żądany identyfikator URI.

Poniższy kod zmienia domyślną nazwę pliku na mydefault.html:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

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

app.UseStaticFiles();

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

UseFileServer dla dokumentów domyślnych

UseFileServer łączy funkcje UseStaticFiles, UseDefaultFilesi opcjonalnie UseDirectoryBrowser.

Wywołaj metodę app.UseFileServer w celu włączenia obsługi plików statycznych i pliku domyślnego. Przeglądanie katalogów nie jest włączone:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseFileServer();

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Poniższy kod umożliwia obsługę plików statycznych, pliku domyślnego i przeglądania katalogów:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddDirectoryBrowser();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseFileServer(enableDirectoryBrowsing: true);

app.UseRouting();

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Rozważ następującą hierarchię katalogów:

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

Poniższy kod umożliwia obsługę plików statycznych, pliku domyślnego i przeglądania katalogów:MyStaticFiles

using Microsoft.Extensions.FileProviders;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddDirectoryBrowser();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseFileServer(new FileServerOptions
{
    FileProvider = new PhysicalFileProvider(
           Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
    RequestPath = "/StaticFiles",
    EnableDirectoryBrowsing = true
});

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

AddDirectoryBrowser musi być wywoływane, gdy wartość właściwości EnableDirectoryBrowsing wynosi true.

Korzystając z poprzedniej hierarchii plików i kodu, adresy URL są rozpoznawane w następujący sposób:

Identyfikator URI Odpowiedź
https://<hostname>/StaticFiles/images/MyImage.jpg MyStaticFiles/images/MyImage.jpg
https://<hostname>/StaticFiles MyStaticFiles/default.html

Jeśli w katalogu MyStaticFiles nie istnieje żaden plik o nazwie domyślnej, https://<hostname>/StaticFiles zwraca listę katalogów z linkami, które można kliknąć:

Lista plików statycznych

UseDefaultFiles i UseDirectoryBrowser wykonują przekierowanie po stronie klienta z docelowego URI bez końcowego / do docelowego URI z końcowym /. Na przykład od https://<hostname>/StaticFiles do https://<hostname>/StaticFiles/. Względne adresy URL w katalogu StaticFiles są nieprawidłowe bez ukośnika na końcu (/), chyba że jest używana opcja DefaultFilesOptions.

FileExtensionContentTypeProvider

Klasa FileExtensionContentTypeProvider zawiera Mappings właściwość, która służy jako mapowanie rozszerzeń plików na typy zawartości MIME. W poniższym przykładzie kilka rozszerzeń plików jest mapowanych na znane typy MIME. Rozszerzenie .rtf jest zastępowane i .mp4 jest usuwane:

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

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

// 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
{
    ContentTypeProvider = provider
});

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Zobacz Typy zawartości MIME.

Niestandardowe typy zawartości

Oprogramowanie pośredniczące plików statycznych rozumie prawie 400 znanych typów zawartości plików. Jeśli użytkownik żąda pliku z nieznanym typem, oprogramowanie pośredniczące do obsługi plików statycznych przekazuje żądanie do następnego oprogramowania pośredniczącego w sekwencji przetwarzania. Jeśli żadne oprogramowanie pośredniczące nie obsługuje żądania, zostanie zwrócona odpowiedź 404 Nie znaleziono . Jeśli przeglądanie katalogów jest włączone, link do pliku jest wyświetlany na liście katalogów.

Poniższy kod umożliwia obsługę nieznanych typów i renderuje nieznany plik jako obraz:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

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

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

W poprzednim kodzie żądanie pliku o nieznanym typie zawartości jest zwracane jako obraz.

Ostrzeżenie

ServeUnknownFileTypes Włączenie jest zagrożeniem bezpieczeństwa. Jest on domyślnie wyłączony, a jego użycie jest odradzane. FileExtensionContentTypeProvider zapewnia bezpieczniejszą alternatywę dla obsługi plików z niestandardowymi rozszerzeniami.

Obsługa plików z wielu lokalizacji

Rozważmy następującą Razor stronę, na której jest wyświetlany /MyStaticFiles/image3.png plik:

@page

<p> Test /MyStaticFiles/image3.png</p>

<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">

UseStaticFiles i UseFileServer domyślnie do dostawcy plików wskazujących na wwwroot. Dodatkowe instancje UseStaticFiles i UseFileServer mogą być udostępniane innym dostawcom plików w celu serwowania plików z innych lokalizacji. Poniższy przykład wywołuje UseStaticFiles dwa razy, aby obsługiwać pliki z wwwroot i MyStaticFiles.

app.UseStaticFiles(); // Serve files from wwwroot
app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});

Przy użyciu poprzedniego kodu:

Poniższy kod aktualizuje element WebRootFileProvider, który umożliwia pomocnikowi tagów obrazów podanie wersji:

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

var compositeProvider = new CompositeFileProvider(webRootProvider,
                                                  newPathProvider);

// Update the default provider.
app.Environment.WebRootFileProvider = compositeProvider;

app.UseStaticFiles();

Uwaga

Powyższe podejście dotyczy Razor aplikacji Pages i MVC. Aby uzyskać wskazówki dotyczące Blazor Web App, zobacz statyczne pliki Blazor ASP.NET Core.

Zagadnienia dotyczące zabezpieczeń plików statycznych

Ostrzeżenie

UseDirectoryBrowser i UseStaticFiles mogą wyciekać tajemnice. Wyłączenie przeglądania katalogów w środowisku produkcyjnym jest zdecydowanie zalecane. Dokładnie sprawdź, które katalogi są włączone za pomocą UseStaticFiles lub UseDirectoryBrowser. Cały katalog i jego podkatalog stają się publicznie dostępne. Przechowuj pliki odpowiednie do obsługi publicznej w dedykowanym katalogu, takim jak <content_root>/wwwroot. Oddziel te pliki od widoków MVC, Razor stron, plików konfiguracji itp.

  • Adresy URL dla zawartości ujawnionej za pomocą UseDirectoryBrowser i UseStaticFiles podlegają ograniczeniom związanym z wrażliwością na wielkość liter i znaków w podstawowym systemie plików. Na przykład system Windows jest nieczuły na wielkość liter, ale systemy macOS i Linux uwzględniają wielkość liter.

  • Aplikacje ASP.NET Core hostowane w IIS używają modułu ASP.NET Core do przekazywania wszystkich żądań do aplikacji, w tym żądań plików statycznych. Obsługiwacz plików statycznych w IIS nie jest używany i nie może obsługiwać żądań.

  • Wykonaj następujące kroki w Menedżerze usług IIS, aby usunąć program obsługi plików statycznych usług IIS na poziomie serwera lub witryny internetowej:

    1. Przejdź do funkcji Moduły .
    2. Wybierz pozycję StaticFileModule na liście.
    3. Kliknij przycisk Usuń na pasku bocznym Akcje .

Ostrzeżenie

Jeśli program obsługi plików statycznych w usługach IIS jest włączony i moduł ASP.NET Core jest niepoprawnie skonfigurowany, pliki statyczne mogą być obsługiwane. Dzieje się tak, na przykład jeśli plik web.config nie jest wdrożony.

  • Umieść pliki kodu, w tym .cs i .cshtml, poza katalogem głównym projektu aplikacji. Dlatego separacja logiczna jest tworzona między zawartością po stronie klienta aplikacji a kodem opartym na serwerze. Zapobiega to wyciekowi kodu po stronie serwera.

Udostępnianie plików spoza wwwroot przez aktualizację IWebHostEnvironment.WebRootPath

Gdy IWebHostEnvironment.WebRootPath jest ustawiony na folder inny niż wwwroot:

  • W środowisku projektowym zasoby statyczne znajdujące się zarówno w wwwroot, jak i w zaktualizowanym IWebHostEnvironment.WebRootPath są obsługiwane z serwera wwwroot.
  • W każdym środowisku innym niż tworzenie, zduplikowane zasoby statyczne są serwowane z zaktualizowanego folderu IWebHostEnvironment.WebRootPath.

Rozważmy aplikację internetową utworzoną przy użyciu pustego szablonu internetowego:

  • Zawiera plik Index.html w plikach wwwroot i wwwroot-custom.

  • Przy użyciu następującego zaktualizowanego Program.cs pliku, który ustawia wartość WebRootPath = "wwwroot-custom":

    var builder = WebApplication.CreateBuilder(new WebApplicationOptions
    {
        Args = args,
        // Look for static files in "wwwroot-custom"
        WebRootPath = "wwwroot-custom"
    });
    
    var app = builder.Build();
    
    app.UseDefaultFiles();
    app.UseStaticFiles();
    
    app.Run();
    

W poprzednim kodzie żądania do /:

  • W środowisku deweloperskim zwróć wwwroot/Index.html
  • W dowolnym środowisku innym niż programistyczne zwróć wwwroot-custom/Index.html

Aby upewnić się, że zasoby z wwwroot-custom zostaną zwrócone, użyj jednego z następujących metod:

  • Usuń zduplikowane nazwane zasoby w wwwroot.

  • Ustaw "ASPNETCORE_ENVIRONMENT" w Properties/launchSettings.json na dowolną wartość inną niż "Development".

  • Całkowicie wyłącz statyczne zasoby internetowe przez ustawienie <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled> w pliku projektu. OSTRZEŻENIE, wyłączenie statycznych zasobów internetowych powoduje wyłączenie Razor bibliotek klas.

  • Dodaj następujący kod JSON do pliku projektu:

    <ItemGroup>
        <Content Remove="wwwroot\**" />
    </ItemGroup>
    

Poniższy kod aktualizuje IWebHostEnvironment.WebRootPath na wartość niezwiązaną z programowaniem, co gwarantuje, że zduplikowana zawartość zostanie zwrócona z wwwroot-custom zamiast z wwwroot.

var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    Args = args,
    // Examine Hosting environment: logging value
    EnvironmentName = Environments.Staging,
    WebRootPath = "wwwroot-custom"
});

var app = builder.Build();

app.Logger.LogInformation("ASPNETCORE_ENVIRONMENT: {env}",
      Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));

app.Logger.LogInformation("app.Environment.IsDevelopment(): {env}",
      app.Environment.IsDevelopment().ToString());

app.UseDefaultFiles();
app.UseStaticFiles();

app.Run();

Dodatkowe zasoby

Autorzy: Rick Anderson i Kirk Larkin

Pliki statyczne, takie jak HTML, CSS, images i JavaScript, to zasoby, które ASP.NET Aplikacja Core domyślnie obsługuje bezpośrednio klientom.

Obsługa plików statycznych

Pliki statyczne są przechowywane w katalogu głównym projektu. Domyślny katalog to {content root}/wwwroot, ale można go zmienić za pomocą UseWebRoot metody . Aby uzyskać więcej informacji, zobacz Katalog główny zawartości oraz Katalog główny sieci Web.

Metoda CreateBuilder ustawia katalog główny zawartości na bieżący katalog:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Pliki statyczne są dostępne za pośrednictwem ścieżki względem katalogu głównego sieci Web. Na przykład szablony projektów aplikacji internetowej zawierają kilka folderów w folderze wwwroot :

  • wwwroot
    • css
    • js
    • lib

Rozważ utworzenie folderu wwwroot/images i dodanie wwwroot/images/MyImage.jpg pliku. Format identyfikatora URI umożliwiający dostęp do pliku w folderze images to https://<hostname>/images/<image_file_name>. Na przykład https://localhost:5001/images/MyImage.jpg

Udostępnianie plików w katalogu głównym sieci Web

Domyślne szablony aplikacji internetowej wywołają metodę UseStaticFiles w Program.cs, co umożliwia obsługę plików statycznych:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Przeciążenie metody bezparametrowej oznacza pliki w katalogu głównym sieci Web jako dostępne do serwowania. Następujące referencje do znaczników wwwroot/images/MyImage.jpg:

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

Znak tyldy ~ w poprzednim znaczniku wskazuje na root sieciowy.

Serwowanie plików spoza katalogu głównego serwera WWW

Rozważ hierarchię katalogów, w której pliki statyczne, które mają być obsługiwane, znajdują się poza katalogiem głównym sieci Web:

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

Żądanie może uzyskać dostęp do pliku red-rose.jpg poprzez skonfigurowanie pośrednictwa dla plików statycznych w następujący sposób:

using Microsoft.Extensions.FileProviders;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
           Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
    RequestPath = "/StaticFiles"
});

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

W poprzednim kodzie hierarchia katalogów MyStaticFiles jest uwidoczniona publicznie za pośrednictwem segmentu identyfikatora URI StaticFiles . Żądanie do https://<hostname>/StaticFiles/images/red-rose.jpg dostarcza plik red-rose.jpg.

Następujące odwołania do znaczników MyStaticFiles/images/red-rose.jpg:

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

Aby obsłużyć pliki z wielu lokalizacji, zobacz Obsługa plików z wielu lokalizacji.

Ustawianie nagłówków odpowiedzi HTTP

Obiekt StaticFileOptions może służyć do ustawiania nagłówków odpowiedzi HTTP. Oprócz konfigurowania serwowania plików statycznych z katalogu głównego w sieci Web, następujący kod ustawia nagłówek Cache-Control:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

var cacheMaxAgeOneWeek = (60 * 60 * 24 * 7).ToString();
app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = ctx =>
    {
        ctx.Context.Response.Headers.Append(
             "Cache-Control", $"public, max-age={cacheMaxAgeOneWeek}");
    }
});

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Powyższy kod udostępnia pliki statyczne publicznie w lokalnej pamięci podręcznej przez tydzień (604800 sekund).

Autoryzacja pliku statycznego

Szablony ASP.NET Core wywołują UseStaticFiles przed wywołaniem UseAuthorization. Większość aplikacji podąża za tym wzorcem. Gdy oprogramowanie pośredniczące plików statycznych jest wywoływane przed oprogramowaniem pośredniczącym autoryzacji:

  • W plikach statycznych nie są wykonywane kontrole autoryzacji.
  • Pliki statyczne obsługiwane przez middleware plików statycznych, takie jak w obszarze wwwroot, są publicznie dostępne.

Aby obsługiwać pliki statyczne na podstawie autoryzacji:

  • Przechowuj je poza elementem wwwroot.
  • Wywołaj metodę UseStaticFiles, określając ścieżkę po wywołaniu metody UseAuthorization.
  • Ustaw zapasowe zasady autoryzacji.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using StaticFileAuth.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

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

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
           Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
    RequestPath = "/StaticFiles"
});

app.MapRazorPages();

app.Run();

W poprzednim kodzie zasady autoryzacji rezerwowej wymagają uwierzytelnienia wszystkich użytkowników. Punkty końcowe, takie jak kontrolery, Razor strony itp., które określają własne wymagania dotyczące autoryzacji, nie korzystają z zasad autoryzacji rezerwowej. Na przykład Razor strony, kontrolery lub metody akcji z zastosowaniem [AllowAnonymous] lub [Authorize(PolicyName="MyPolicy")] używają przypisanego atrybutu autoryzacji zamiast rezerwowej polityki autoryzacji.

RequireAuthenticatedUser dodaje DenyAnonymousAuthorizationRequirement do bieżącego wystąpienia, co wymusza uwierzytelnienie bieżącego użytkownika.

Zasoby statyczne w obszarze wwwroot są publicznie dostępne, ponieważ domyślne oprogramowanie pośredniczące plików statycznych (app.UseStaticFiles();) jest wywoływane przed UseAuthentication. Zasoby statyczne w folderze MyStaticFiles wymagają uwierzytelniania. Przykładowy kod pokazuje to.

Alternatywną metodą udostępniania plików na podstawie autoryzacji jest:

  • Przechowuj je poza katalogami wwwroot i tymi, do których dostęp ma oprogramowanie pośredniczące do plików statycznych.
  • Serwuj je za pomocą metody akcji, do której zastosowano autoryzację, i zwróć obiekt FileResult.
[Authorize]
public class BannerImageModel : PageModel
{
    private readonly IWebHostEnvironment _env;

    public BannerImageModel(IWebHostEnvironment env) =>
        _env = env;

    public PhysicalFileResult OnGet()
    {
        var filePath = Path.Combine(
                _env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");

        return PhysicalFile(filePath, "image/jpeg");
    }
}

Przeglądanie katalogów

Przeglądanie katalogów umożliwia wyświetlanie listy katalogów w określonych katalogach.

Przeglądanie katalogów jest domyślnie wyłączone ze względów bezpieczeństwa. Aby uzyskać więcej informacji, zobacz Zagadnienia dotyczące zabezpieczeń plików statycznych.

Włącz przeglądanie katalogów za pomocą polecenia AddDirectoryBrowser i UseDirectoryBrowser:

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

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddDirectoryBrowser();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

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

// Enable displaying browser links.
app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = fileProvider,
    RequestPath = requestPath
});

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

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Powyższy kod umożliwia przeglądanie katalogów folderu wwwroot/images przy użyciu adresu URL https://<hostname>/MyImages, z linkami do każdego pliku i folderu:

przeglądanie katalogów

AddDirectoryBrowser dodaje usługi wymagane przez oprogramowanie pośredniczące przeglądania katalogów, w tym HtmlEncoder. Te usługi mogą być dodawane przez inne wywołania, takie jak AddRazorPages, ale zalecamy wywołanie, AddDirectoryBrowser aby upewnić się, że usługi są dodawane we wszystkich aplikacjach.

Obsługa dokumentów domyślnych

Ustawienie strony domyślnej zapewnia odwiedzającym punkt początkowy w witrynie. Aby obsłużyć domyślny plik z wwwroot bez konieczności uwzględniania nazwy pliku w żądaniu URL, wywołaj metodę UseDefaultFiles.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseDefaultFiles();

app.UseStaticFiles();
app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

UseDefaultFiles musi być wywoływana przed UseStaticFiles udostępnieniem pliku domyślnego. UseDefaultFiles jest narzędziem do przepisywania adresów URL, który nie serwuje pliku.

W przypadku UseDefaultFiles, żądania do folderu w wwwroot wyszukiwane są:

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

Pierwszy plik znaleziony na liście jest obsługiwany tak, jakby żądanie zawierało nazwę pliku. Adres URL przeglądarki nadal odzwierciedla żądany identyfikator URI.

Poniższy kod zmienia domyślną nazwę pliku na mydefault.html:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

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

app.UseStaticFiles();

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

UseFileServer dla dokumentów domyślnych

UseFileServer łączy funkcje UseStaticFiles, UseDefaultFilesi opcjonalnie UseDirectoryBrowser.

Wywołaj metodę app.UseFileServer w celu włączenia obsługi plików statycznych i pliku domyślnego. Przeglądanie katalogów nie jest włączone:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseFileServer();

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Poniższy kod umożliwia obsługę plików statycznych, pliku domyślnego i przeglądania katalogów:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddDirectoryBrowser();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseFileServer(enableDirectoryBrowsing: true);

app.UseRouting();

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Rozważ następującą hierarchię katalogów:

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

Poniższy kod umożliwia obsługę plików statycznych, pliku domyślnego i przeglądania katalogów:MyStaticFiles

using Microsoft.Extensions.FileProviders;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddDirectoryBrowser();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseFileServer(new FileServerOptions
{
    FileProvider = new PhysicalFileProvider(
           Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
    RequestPath = "/StaticFiles",
    EnableDirectoryBrowsing = true
});

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

AddDirectoryBrowser musi być wywoływany, gdy wartość właściwości EnableDirectoryBrowsing to true.

Korzystając z poprzedniej hierarchii plików i kodu, adresy URL są rozpoznawane w następujący sposób:

Identyfikator URI Odpowiedź
https://<hostname>/StaticFiles/images/MyImage.jpg MyStaticFiles/images/MyImage.jpg
https://<hostname>/StaticFiles MyStaticFiles/default.html

Jeśli w katalogu MyStaticFiles nie istnieje żaden plik o nazwie domyślnej, https://<hostname>/StaticFiles zwraca listę katalogów z linkami, które można kliknąć:

Lista plików statycznych

UseDefaultFiles i UseDirectoryBrowser wykonują przekierowanie po stronie klienta z docelowego URI bez końcowego / do docelowego URI z końcowym /. Na przykład od https://<hostname>/StaticFiles do https://<hostname>/StaticFiles/. Względne adresy URL w katalogu StaticFiles są nieprawidłowe bez końcowego ukośnika (/), chyba że używana jest opcja DefaultFilesOptionsRedirectToAppendTrailingSlash.

FileExtensionContentTypeProvider

Klasa FileExtensionContentTypeProvider zawiera Mappings właściwość, która służy jako mapowanie rozszerzeń plików na typy zawartości MIME. W poniższym przykładzie kilka rozszerzeń plików jest mapowanych na znane typy MIME. Rozszerzenie .rtf jest zastępowane i .mp4 jest usuwane:

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

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

// 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
{
    ContentTypeProvider = provider
});

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Zobacz Typy zawartości MIME.

Niestandardowe typy zawartości

Oprogramowanie pośredniczące plików statycznych rozumie prawie 400 znanych typów zawartości plików. Jeśli użytkownik żąda pliku z nieznanym typem pliku, oprogramowanie static file middleware przekazuje żądanie do następnego oprogramowania pośredniczącego w potoku. Jeśli żadne oprogramowanie pośredniczące nie obsługuje żądania, zostanie zwrócona odpowiedź 404 Nie znaleziono . Jeśli przeglądanie katalogów jest włączone, link do pliku jest wyświetlany na liście katalogów.

Poniższy kod umożliwia obsługę nieznanych typów i renderuje nieznany plik jako obraz:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

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

app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

W poprzednim kodzie żądanie pliku o nieznanym typie zawartości jest zwracane jako obraz.

Ostrzeżenie

ServeUnknownFileTypes Włączenie jest zagrożeniem bezpieczeństwa. Jest on domyślnie wyłączony, a jego użycie jest odradzane. FileExtensionContentTypeProvider zapewnia bezpieczniejszą alternatywę dla obsługi plików z niestandardowymi rozszerzeniami.

Obsługa plików z wielu lokalizacji

Rozważmy następującą Razor stronę, na której jest wyświetlany /MyStaticFiles/image3.png plik:

@page

<p> Test /MyStaticFiles/image3.png</p>

<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">

UseStaticFiles i UseFileServer domyślnie używają dostawcy plików wskazującego na wwwroot. Dodatkowe wystąpienia UseStaticFiles i UseFileServer mogą być dostarczane przez innych dostawców usług plikowych do obsługi plików z innych lokalizacji. Poniższy przykład wywołuje UseStaticFiles dwa razy, aby obsługiwać pliki z wwwroot i MyStaticFiles.

app.UseStaticFiles(); // Serve files from wwwroot
app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});

Przy użyciu poprzedniego kodu:

Poniższy kod aktualizuje element WebRootFileProvider, który umożliwia pomocnikowi tagów obrazów podanie wersji:

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

var compositeProvider = new CompositeFileProvider(webRootProvider,
                                                  newPathProvider);

// Update the default provider.
app.Environment.WebRootFileProvider = compositeProvider;

app.UseStaticFiles();

Zagadnienia dotyczące zabezpieczeń plików statycznych

Ostrzeżenie

UseDirectoryBrowser i UseStaticFiles mogą wyciekać tajemnice. Wyłączenie przeglądania katalogów w środowisku produkcyjnym jest zdecydowanie zalecane. Dokładnie sprawdź, które katalogi są włączone przez UseStaticFiles lub UseDirectoryBrowser. Cały katalog i jego podkatalog stają się publicznie dostępne. Przechowuj pliki odpowiednie do obsługi publicznej w dedykowanym katalogu, takim jak <content_root>/wwwroot. Oddziel te pliki od widoków MVC, Razor stron, plików konfiguracji itp.

  • Adresy URL dla zawartości udostępnionej za pomocą UseDirectoryBrowser i UseStaticFiles podlegają rozróżnieniu wielkości liter oraz ograniczeniom znaków w podstawowym systemie plików. Na przykład, system Windows jest niewrażliwy na wielkość liter, ale macOS i Linux są wrażliwe.

  • Aplikacje ASP.NET Core hostowane w usługach IIS używają modułu ASP.NET Core do przekazywania wszystkich żądań do aplikacji, w tym żądań plików statycznych. Program obsługi plików statycznych usług IIS nie jest używany i nie może obsługiwać żądań.

  • Wykonaj następujące kroki w Menedżerze usług IIS, aby usunąć program obsługi plików statycznych usług IIS na poziomie serwera lub witryny internetowej:

    1. Przejdź do funkcji Moduły .
    2. Wybierz pozycję StaticFileModule na liście.
    3. Kliknij przycisk Usuń na pasku bocznym Akcje .

Ostrzeżenie

Jeśli program obsługi plików statycznych usług IIS jest włączony , a moduł ASP.NET Core jest niepoprawnie skonfigurowany, obsługiwane są pliki statyczne. Dzieje się tak, na przykład jeśli plik web.config nie jest wdrożony.

  • Umieść pliki kodu, w tym .cs i .cshtml, poza katalogem głównym projektu aplikacji. Dlatego separacja logiczna jest tworzona między zawartością po stronie klienta aplikacji a kodem opartym na serwerze. Zapobiega to wyciekowi kodu po stronie serwera.

Serwowanie plików spoza katalogu wwwroot przez zaktualizowanie parametru IWebHostEnvironment.WebRootPath

Gdy IWebHostEnvironment.WebRootPath jest ustawiony na folder inny niż wwwroot:

  • W środowisku projektowym zasoby statyczne znajdujące się zarówno w wwwroot, jak i w zaktualizowanym IWebHostEnvironment.WebRootPath są obsługiwane z wwwroot.
  • W każdym środowisku innym niż deweloperskie, duplikaty zasobów statycznych są obsługiwane z zaktualizowanego folderu IWebHostEnvironment.WebRootPath.

Rozważmy aplikację internetową utworzoną przy użyciu pustego szablonu internetowego:

  • Zawiera plik Index.html w plikach wwwroot i wwwroot-custom.

  • Przy użyciu następującego zaktualizowanego Program.cs pliku, który ustawia wartość WebRootPath = "wwwroot-custom":

    var builder = WebApplication.CreateBuilder(new WebApplicationOptions
    {
        Args = args,
        // Look for static files in "wwwroot-custom"
        WebRootPath = "wwwroot-custom"
    });
    
    var app = builder.Build();
    
    app.UseDefaultFiles();
    app.UseStaticFiles();
    
    app.Run();
    

W poprzednim kodzie żądania składane do /:

  • W środowisku deweloperskim zwróć wwwroot/Index.html
  • W dowolnym środowisku innym niż środowisko programistyczne zwróć wwwroot-custom/Index.html

Aby upewnić się, że zasoby z wwwroot-custom zostaną zwrócone, użyj jednego z następujących podejść:

  • Usuń zduplikowane nazwane zasoby w wwwroot.

  • Ustaw "ASPNETCORE_ENVIRONMENT" w Properties/launchSettings.json na dowolną wartość inną niż "Development".

  • Całkowicie wyłącz statyczne zasoby internetowe przez ustawienie <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled> w pliku projektu. OSTRZEŻENIE, wyłączenie statycznych zasobów internetowych powoduje wyłączenie Razor bibliotek klas.

  • Dodaj następujący kod JSON do pliku projektu:

    <ItemGroup>
        <Content Remove="wwwroot\**" />
    </ItemGroup>
    

Poniższy kod aktualizuje IWebHostEnvironment.WebRootPath wartość niezwiązaną z programowaniem, co gwarantuje zwrócenie wwwroot-custom zduplikowanej zawartości zamiast wwwroot:

var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    Args = args,
    // Examine Hosting environment: logging value
    EnvironmentName = Environments.Staging,
    WebRootPath = "wwwroot-custom"
});

var app = builder.Build();

app.Logger.LogInformation("ASPNETCORE_ENVIRONMENT: {env}",
      Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));

app.Logger.LogInformation("app.Environment.IsDevelopment(): {env}",
      app.Environment.IsDevelopment().ToString());

app.UseDefaultFiles();
app.UseStaticFiles();

app.Run();

Dodatkowe zasoby

Autorzy: Rick Anderson i Kirk Larkin

Pliki statyczne, takie jak HTML, CSS, images i JavaScript, to zasoby, które ASP.NET Aplikacja Core domyślnie obsługuje bezpośrednio klientom.

Wyświetl lub pobierz przykładowy kod (jak pobrać)

Obsługa plików statycznych

Pliki statyczne są przechowywane w katalogu głównym projektu. Domyślny katalog to {content root}/wwwroot, ale można go zmienić za pomocą UseWebRoot metody . Aby uzyskać więcej informacji, zobacz Katalog główny Zawartości i Katalog główny Witryny.

Metoda CreateDefaultBuilder ustawia katalog główny zawartości na bieżący katalog:

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

Poprzedni kod został utworzony za pomocą szablonu aplikacji internetowej.

Pliki statyczne są dostępne za pośrednictwem ścieżki względem katalogu głównego sieci Web. Na przykład szablony projektów aplikacji internetowej zawierają kilka folderów w folderze wwwroot :

  • wwwroot
    • css
    • js
    • lib

Rozważ utworzenie folderu wwwroot/images i dodanie wwwroot/images/MyImage.jpg pliku. Format identyfikatora URI umożliwiający dostęp do pliku w folderze images to https://<hostname>/images/<image_file_name>. Na przykład https://localhost:5001/images/MyImage.jpg

Obsługa plików w katalogu głównym sieci Web

Domyślne szablony aplikacji internetowej wywołują metodę UseStaticFiles w Startup.Configure, co umożliwia obsługę plików statycznych:

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

Przeciążenie metody bezparametrowej oznacza pliki w głównym katalogu sieciowym jako dostępne. Następujące odwołania do znaczników: wwwroot/images/MyImage.jpg

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

W poprzednim kodzie tylda ~/ wskazuje na korzeń webowy.

Serwowanie plików spoza katalogu głównego sieci Web

Rozważ hierarchię katalogów, w której pliki statyczne, które mają być obsługiwane, znajdują się poza katalogiem głównym sieci Web:

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

Żądanie może uzyskać dostęp do pliku red-rose.jpg, konfigurując oprogramowanie pośredniczące dla plików statycznych w następujący sposób:

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

W poprzednim kodzie hierarchia katalogów MyStaticFiles jest uwidoczniona publicznie za pośrednictwem segmentu identyfikatora URI StaticFiles . Żądanie do https://<hostname>/StaticFiles/images/red-rose.jpg obsługuje plik red-rose.jpg.

Następujący znacznik odnosi się do MyStaticFiles/images/red-rose.jpg:

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

Ustawianie nagłówków odpowiedzi HTTP

Obiekt StaticFileOptions może służyć do ustawiania nagłówków odpowiedzi HTTP. Oprócz konfigurowania obsługi plików statycznych z katalogu głównego serwera, następujący kod ustawia nagłówek:

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

Poprzedni kod ustawia maksymalny wiek na 604800 sekund (7 dni).

Nagłówki odpowiedzi z dodanym nagłówkem Cache-Control

Autoryzacja pliku statycznego

Szablony ASP.NET Core wywołują UseStaticFiles przed wywołaniem UseAuthorization. Większość aplikacji podąża za tym wzorcem. Gdy oprogramowanie pośredniczące plików statycznych jest wywoływane przed oprogramowaniem pośredniczącym autoryzacji:

  • W plikach statycznych nie są wykonywane kontrole autoryzacji.
  • Oprogramowanie pośredniczące (Middleware) do obsługi plików statycznych, takie jak te w obszarze wwwroot, jest publicznie dostępne.

Aby obsługiwać pliki statyczne na podstawie autoryzacji:

  • Przechowuj je poza elementem wwwroot.
  • Wywołaj metodę UseStaticFiles, określając ścieżkę po wywołaniu metody UseAuthorization.
  • Ustaw zasady autoryzacji zapasowej.
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();
    });
}
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.

W poprzednim kodzie zasady autoryzacji rezerwowej wymagają uwierzytelnienia wszystkich użytkowników. Punkty końcowe, takie jak kontrolery, Razor strony itp., które określają własne wymagania dotyczące autoryzacji, nie korzystają z zasad autoryzacji rezerwowej. Na przykład Razor strony, kontrolery lub metody akcji używają zastosowanego atrybutu autoryzacji [AllowAnonymous] lub [Authorize(PolicyName="MyPolicy")] zamiast zasad autoryzacji rezerwowej.

RequireAuthenticatedUser dodaje DenyAnonymousAuthorizationRequirement do bieżącego wystąpienia, co wymusza uwierzytelnienie bieżącego użytkownika.

Zasoby statyczne w obszarze wwwroot są publicznie dostępne, ponieważ domyślne oprogramowanie pośredniczące plików statycznych (app.UseStaticFiles();) jest wywoływane przed UseAuthentication. Zasoby statyczne w folderze MyStaticFiles wymagają uwierzytelniania. Przykładowy kod pokazuje to.

Alternatywną metodą udostępniania plików na podstawie autoryzacji jest:

  • Przechowuj je poza wwwroot oraz poza dowolnym katalogiem dostępnym dla oprogramowania pośredniczącego plików statycznych.
  • Podawaj je za pomocą metody akcji, do której stosuje się autoryzację, i zwróć obiekt FileResult.
[Authorize]
public IActionResult BannerImage()
{
    var filePath = Path.Combine(
        _env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");

    return PhysicalFile(filePath, "image/jpeg");
}

Przeglądanie katalogów

Przeglądanie katalogów umożliwia wyświetlanie listy katalogów w określonych katalogach.

Przeglądanie katalogów jest domyślnie wyłączone ze względów bezpieczeństwa. Aby uzyskać więcej informacji, zobacz Zagadnienia dotyczące zabezpieczeń plików statycznych.

Włącz przeglądanie katalogów za pomocą:

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

Powyższy kod umożliwia przeglądanie katalogów folderu wwwroot/images przy użyciu adresu URL https://<hostname>/MyImages, z linkami do każdego pliku i folderu:

przeglądanie katalogów

Obsługa dokumentów domyślnych

Ustawienie strony domyślnej zapewnia odwiedzającym punkt początkowy w witrynie. Aby obsłużyć plik domyślny z wwwroot bez konieczności wymagania, aby adres URL żądania zawierał nazwę pliku, wywołaj metodę UseDefaultFiles.

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

UseDefaultFiles musi być wywołana przed UseStaticFiles, aby udostępnić plik domyślny. UseDefaultFiles jest narzędziem do przepisywania adresów URL, które nie serwuje pliku.

Za pomocą UseDefaultFiles, żądania do folderu w wwwroot wyszukują:

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

Pierwszy plik znaleziony na liście jest obsługiwany tak, jakby żądanie zawierało nazwę pliku. Adres URL przeglądarki nadal odzwierciedla żądany identyfikator URI.

Poniższy kod zmienia domyślną nazwę pliku na mydefault.html:

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

Poniższy kod przedstawia Startup.Configure wraz z poprzednim kodem.

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 dla dokumentów domyślnych

UseFileServer łączy funkcje UseStaticFiles, UseDefaultFilesi opcjonalnie UseDirectoryBrowser.

Wywołaj metodę app.UseFileServer w celu włączenia obsługi plików statycznych i pliku domyślnego. Przeglądanie katalogów nie jest włączone. Poniższy kod przedstawia kod Startup.Configure z elementem UseFileServer:

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

Poniższy kod umożliwia obsługę plików statycznych, pliku domyślnego i przeglądania katalogów:

app.UseFileServer(enableDirectoryBrowsing: true);

Poniższy kod przedstawia Startup.Configure z poprzednim kodem:

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

Rozważ następującą hierarchię katalogów:

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

Poniższy kod umożliwia obsługę plików statycznych, pliku domyślnego i przeglądania katalogów:MyStaticFiles

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

AddDirectoryBrowser musi być wywołany, gdy wartość właściwości EnableDirectoryBrowsing to true.

Korzystając z hierarchii plików i poprzedniego kodu, adresy URL są rozpoznawane w następujący sposób:

Identyfikator URI Odpowiedź
https://<hostname>/StaticFiles/images/MyImage.jpg MyStaticFiles/images/MyImage.jpg
https://<hostname>/StaticFiles MyStaticFiles/default.html

Jeśli w katalogu MyStaticFiles nie istnieje żaden plik o nazwie domyślnej, https://<hostname>/StaticFiles zwraca listę katalogów z linkami, które można kliknąć:

Lista plików statycznych

UseDefaultFiles i UseDirectoryBrowser wykonują przekierowanie po stronie klienta z docelowego URI bez końcowego / na docelowy URI z końcowym /. Na przykład od https://<hostname>/StaticFiles do https://<hostname>/StaticFiles/. Względne adresy URL w katalogu StaticFiles są nieprawidłowe bez końcowego ukośnika (/).

FileExtensionContentTypeProvider

Klasa FileExtensionContentTypeProvider zawiera Mappings właściwość, która służy jako mapowanie rozszerzeń plików na typy zawartości MIME. W poniższym przykładzie kilka rozszerzeń plików jest mapowanych na znane typy MIME. Rozszerzenie .rtf jest zastępowane i .mp4 jest usuwane:

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

Oto kod pokazujący Startup.Configure wraz z poprzedzającym kodem.

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

Zobacz Typy zawartości MIME.

Niestandardowe typy zawartości

Oprogramowanie pośredniczące plików statycznych rozumie prawie 400 znanych typów zawartości plików. Jeśli użytkownik żąda pliku z nieznanym typem pliku, pośrednik plików statycznych przekazuje żądanie do kolejnego pośrednika w potoku. Jeśli żadne oprogramowanie pośredniczące nie obsługuje żądania, zostanie zwrócona odpowiedź 404 Nie znaleziono . Jeśli przeglądanie katalogów jest włączone, link do pliku jest wyświetlany na liście katalogów.

Poniższy kod umożliwia obsługę nieznanych typów i renderuje nieznany plik jako obraz:

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

Poniższy kod przedstawia Startup.Configure razem z wcześniejszym kodem:

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

W poprzednim kodzie żądanie pliku o nieznanym typie zawartości jest zwracane jako obraz.

Ostrzeżenie

ServeUnknownFileTypes Włączenie jest zagrożeniem bezpieczeństwa. Jest on domyślnie wyłączony, a jego użycie jest odradzane. FileExtensionContentTypeProvider zapewnia bezpieczniejszą alternatywę dla obsługi plików z niestandardowymi rozszerzeniami.

Obsługa plików z wielu lokalizacji

UseStaticFiles i UseFileServer domyślnie ustawiają się na dostawcę plików wskazującego na wwwroot. Dodatkowe wystąpienia UseStaticFiles i UseFileServer mogą być dostarczone z innymi dostawcami plików, aby udostępniać pliki z innych lokalizacji. Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.

Zagadnienia dotyczące zabezpieczeń plików statycznych

Ostrzeżenie

UseDirectoryBrowser i UseStaticFiles mogą wyciekać tajemnice. Wyłączenie przeglądania katalogów w środowisku produkcyjnym jest zdecydowanie zalecane. Dokładnie sprawdź, które katalogi są włączone przez UseStaticFiles lub UseDirectoryBrowser. Cały katalog i jego podkatalog stają się publicznie dostępne. Przechowuj pliki odpowiednie do obsługi publicznej w dedykowanym katalogu, takim jak <content_root>/wwwroot. Oddziel te pliki od widoków MVC, Razor stron, plików konfiguracji itp.

  • Adresy URL dla zawartości przedstawionej za pomocą UseDirectoryBrowser oraz UseStaticFiles podlegają ograniczeniom dotyczącym wielkości liter i znaków właściwych dla podstawowego systemu plików. Na przykład system Windows ignoruje wielkość liter, ale systemy macOS i Linux ją uwzględniają.

  • ASP.NET Core aplikacje hostowane w IIS używają modułu ASP.NET Core do przekazywania wszystkich żądań do aplikacji, w tym żądań plików statycznych. Program obsługi plików statycznych usług IIS nie jest używany i nie może obsługiwać żądań.

  • Wykonaj następujące kroki w Menedżerze usług IIS, aby usunąć program obsługi plików statycznych usług IIS na poziomie serwera lub witryny internetowej:

    1. Przejdź do funkcji Moduły .
    2. Wybierz pozycję StaticFileModule na liście.
    3. Kliknij przycisk Usuń na pasku bocznym Akcje .

Ostrzeżenie

Jeśli program obsługi plików statycznych usług IIS jest włączony a moduł ASP.NET Core jest niepoprawnie skonfigurowany, pliki statyczne zostaną obsłużone. Dzieje się tak, na przykład jeśli plik web.config nie jest wdrożony.

  • Umieść pliki kodu, w tym .cs i .cshtml, poza katalogem głównym projektu aplikacji. Dlatego separacja logiczna jest tworzona między zawartością po stronie klienta aplikacji a kodem opartym na serwerze. Zapobiega to wyciekowi kodu po stronie serwera.

Dodatkowe zasoby