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 wersję tego artykułu platformy .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 wersję tego artykułu platformy .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ę tego artykułu platformy .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.

Aby uzyskać Blazor wskazówki dotyczące plików statycznych, które dodają lub zastępują wskazówki zawarte w tym artykule, zobacz ASP.NET Core Blazor plików statycznych.

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 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.MapStaticAssets();

app.UseAuthorization();

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

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ż aplikację z plikiem wwwroot/images/MyImage.jpg . 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

MapStaticAssets

Tworzenie wydajnych aplikacji internetowych wymaga optymalizacji dostarczania zasobów do przeglądarki. Możliwe optymalizacje obejmują:

  • Obsłuż dany zasób raz, dopóki plik nie ulegnie zmianie lub przeglądarka wyczyści jego pamięć podręczną. Ustaw nagłówek ETag.
  • Uniemożliwiaj przeglądarce używanie starych lub nieaktualnych zasobów po zaktualizowaniu aplikacji. Ustaw nagłówek Ostatnia modyfikacja.
  • Skonfiguruj odpowiednie nagłówki buforowania.
  • Użyj oprogramowania pośredniczącego buforowania.
  • Jeśli to możliwe, obsłuż skompresowane wersje zasobów.
  • Użyj sieci CDN , aby udostępnić zasoby bliżej użytkownika.
  • Zminimalizuj rozmiar zasobów obsługiwanych w przeglądarce. Ta optymalizacja nie obejmuje minification.

MapStaticAssets to konwencje punktów końcowych routingu, które optymalizują dostarczanie zasobów statycznych w aplikacji. Jest ona przeznaczona do pracy ze wszystkimi strukturami interfejsu użytkownika, w tym Blazorz elementami , Razor Pages i MVC.

UseStaticFiles Obsługuje również pliki statyczne, ale nie zapewnia tego samego poziomu optymalizacji co MapStaticAssets. Aby zapoznać się z porównaniem elementów UseStaticFiles i MapStaticAssets, zobacz Optymalizowanie statycznego dostarczania zasobów internetowych.

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

Domyślne szablony aplikacji internetowej wywołają metodę MapStaticAssets w Program.cspliku , która 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.MapStaticAssets();

app.UseAuthorization();

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

app.Run();

Przeciążenie metody bez UseStaticFiles parametrów oznacza pliki w katalogu głównym sieci Web jako możliwe. Następujące odwołania wwwroot/images/MyImage.jpgdo znaczników:

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

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

Obsługa 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 red-rose.jpg pliku, konfigurując oprogramowanie pośredniczące pliku statycznego 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();    //Serve files from wwwroot
app.UseStaticFiles(new StaticFileOptions
 {
     FileProvider = new PhysicalFileProvider(
            Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
     RequestPath = "/StaticFiles"
 });

app.UseAuthorization();

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

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 obsługi red-rose.jpg pliku.

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

<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 plików statycznych obsługujących 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().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();

app.Run();

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

Autoryzacja pliku statycznego

Szablony ASP.NET Core są wywoływane MapStaticAssets przed wywołaniem metody UseAuthorization. Większość aplikacji jest zgodnie z tym wzorcem. Po wywołaniu oprogramowania pośredniczącego plików statycznych przed oprogramowaniem pośredniczącym autoryzacji:

  • W plikach statycznych nie są wykonywane kontrole autoryzacji.
  • Pliki statyczne obsługiwane przez oprogramowanie pośredniczące 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 zasady autoryzacji rezerwowej.
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] autoryzacji lub [Authorize(PolicyName="MyPolicy")] użyj ich, a nie 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 katalogami wwwroot i dostępnymi dla oprogramowania pośredniczącego plików statycznych.

  • Za pomocą metody akcji, do której jest stosowana autoryzacja FileResult i zwraca obiekt:

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

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. See 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();

Plik IFormFile w poprzednim przykładzie używa buforu pamięci do przekazywania. Do obsługi przesyłania strumieniowego dużych plików. Zobacz Przekazywanie dużych plików za pomocą przesyłania strumieniowego.

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.MapStaticAssets();

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().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();

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

AddDirectoryBrowserdodaje 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 bez wwwroot konieczności uwzględnienia nazwy pliku przez adres 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().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();

app.Run();

UseDefaultFiles musi być wywoływana przed UseStaticFiles udostępnieniem pliku domyślnego. UseDefaultFiles jest autorem adresu URL, który nie obsługuje pliku.

Za pomocą polecenia UseDefaultFilesżądania do folderu w wwwroot wyszukiwaniu:

  • 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. Na przykład w przykładowej aplikacji żądanie https://localhost:<port>/def/ obsługi default.html z usługi wwwroot/def.

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().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();

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().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();

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().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();

app.Run();

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

  • wwwroot
    • css
    • images
    • js
  • MyStaticFiles
    • defaultFiles
      • default.html
      • image3.png
    • images
      • MyImage.jpg

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().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();

app.Run();

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

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

Identyfikator URI Response
https://<hostname>/StaticFiles/images/MyImage.jpg MyStaticFiles/images/MyImage.jpg
https://<hostname>/StaticFiles lista katalogów
https://<hostname>/StaticFiles/defaultFiles MyStaticFiles/defaultFiles/default.html
https://<hostname>/StaticFiles/defaultFiles/image3.png MyStaticFiles/defaultFiles//image3.png

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 wykonaj przekierowanie po stronie klienta z docelowego identyfikatora URI bez / końcowego identyfikatora URI z końcowym /identyfikatorem URI. 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 RedirectToAppendTrailingSlash jest używana opcja DefaultFilesOptions .

FileExtensionContentTypeProvider

Klasa FileExtensionContentTypeProvider zawiera właściwość Mapowania , 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().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();

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().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();

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">

UseStaticFilesi UseFileServer domyślnie do dostawcy plików wskazującego wartość .wwwroot Dodatkowe wystąpienia UseStaticFiles programu i UseFileServer mogą być udostępniane innym dostawcom plików w celu udostępniania plików z innych lokalizacji. Poniższy przykład wywołuje dwa razy, UseStaticFiles aby obsługiwać pliki z obu wwwroot elementów i MyStaticFiles:

app.UseStaticFiles();
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.MapStaticAssets();

Uwaga

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

Zagadnienia dotyczące zabezpieczeń plików statycznych

Ostrzeżenie

UseDirectoryBrowser i UseStaticFiles może wyciekać tajemnice. Wyłączenie przeglądania katalogów w środowisku produkcyjnym jest zdecydowanie zalecane. Dokładnie sprawdź, które katalogi są włączone za pośrednictwem programu 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 zawartości udostępnianej za pomocą UseDirectoryBrowserUseStaticFileselementu , i MapStaticAssets podlegają ograniczeniom poufności wielkości liter i znaków bazowego systemu plików. Na przykład system Windows nie uwzględnia wielkości liter, ale systemy macOS i Linux nie są.

  • ASP.NET Core aplikacje hostowane w usługach IIS używają modułu podstawowego ASP.NET 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 ma szans na obsługę żą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.

Obsługa plików poza witryną wwwroot przez zaktualizowanie elementu IWebHostEnvironment.WebRootPath

Gdy IWebHostEnvironment.WebRootPath jest ustawiona wartość folderu innego niż wwwroot:

  • W środowisku projektowym zasoby statyczne znajdujące się zarówno w programie , jak wwwroot i zaktualizowane IWebHostEnvironment.WebRootPath są obsługiwane z witryny wwwroot.
  • W dowolnym środowisku innym niż programowanie zduplikowane zasoby statyczne są obsługiwane ze zaktualizowanego IWebHostEnvironment.WebRootPath folderu.

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.MapStaticAssets();
    
    app.Run();
    

W poprzednim kodzie żądania do /:

  • W zwracaniu środowiska deweloperskiego wwwroot/Index.html
  • W dowolnym środowisku innym niż zwrot programowania wwwroot-custom/Index.html

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

  • Usuń zduplikowane nazwane zasoby w pliku wwwroot.

  • Ustaw "ASPNETCORE_ENVIRONMENT" wartość na Properties/launchSettings.json 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 XML 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.MapStaticAssets();

app.Run();

Dodatkowe zasoby

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 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

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

Domyślne szablony aplikacji internetowej wywołają metodę UseStaticFiles w Program.cspliku , która 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 bez UseStaticFiles parametrów oznacza pliki w katalogu głównym sieci Web jako możliwe. Następujące odwołania wwwroot/images/MyImage.jpgdo znaczników:

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

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

Obsługa 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 red-rose.jpg pliku, konfigurując oprogramowanie pośredniczące pliku statycznego 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 obsługi red-rose.jpg pliku.

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

<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 plików statycznych obsługujących 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 są wywoływane UseStaticFiles przed wywołaniem metody UseAuthorization. Większość aplikacji jest zgodnie z tym wzorcem. Po wywołaniu oprogramowania pośredniczącego plików statycznych przed oprogramowaniem pośredniczącym autoryzacji:

  • W plikach statycznych nie są wykonywane kontrole autoryzacji.
  • Pliki statyczne obsługiwane przez oprogramowanie pośredniczące 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 zasady autoryzacji rezerwowej.
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] autoryzacji lub [Authorize(PolicyName="MyPolicy")] użyj ich, a nie 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 katalogami wwwroot i dostępnymi dla oprogramowania pośredniczącego plików statycznych.

  • Za pomocą metody akcji, do której jest stosowana autoryzacja FileResult i zwraca obiekt:

    [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

AddDirectoryBrowserdodaje 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 bez wwwroot konieczności uwzględnienia nazwy pliku przez adres 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ływana przed UseStaticFiles udostępnieniem pliku domyślnego. UseDefaultFiles jest autorem adresu URL, który nie obsługuje pliku.

Za pomocą polecenia UseDefaultFilesżądania do folderu w wwwroot wyszukiwaniu:

  • 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 element musi być wywoływany, EnableDirectoryBrowsing gdy wartość właściwości to true.

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

Identyfikator URI Response
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 wykonaj przekierowanie po stronie klienta z docelowego identyfikatora URI bez / końcowego identyfikatora URI z końcowym /identyfikatorem URI. 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 RedirectToAppendTrailingSlash 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 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">

UseStaticFilesi UseFileServer domyślnie do dostawcy plików wskazującego wartość .wwwroot Dodatkowe wystąpienia UseStaticFiles programu i UseFileServer mogą być udostępniane innym dostawcom plików w celu udostępniania plików z innych lokalizacji. Poniższy przykład wywołuje dwa razy, UseStaticFiles aby obsługiwać pliki z obu wwwroot elementów 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 Apps, zobacz ASP.NET Core Blazor plików statycznych.

Zagadnienia dotyczące zabezpieczeń plików statycznych

Ostrzeżenie

UseDirectoryBrowser i UseStaticFiles może wyciekać tajemnice. Wyłączenie przeglądania katalogów w środowisku produkcyjnym jest zdecydowanie zalecane. Dokładnie sprawdź, które katalogi są włączone za pośrednictwem programu 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 zawartości uwidocznionej UseDirectoryBrowser UseStaticFiles i podlegają ograniczeniom poufności i znaków wielkości liter w podstawowym systemie plików. Na przykład system Windows nie uwzględnia wielkości liter, ale systemy macOS i Linux nie są.

  • ASP.NET Core aplikacje hostowane w usługach IIS używają modułu podstawowego ASP.NET 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 ma szans na obsługę żą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.

Obsługa plików poza witryną wwwroot przez zaktualizowanie elementu IWebHostEnvironment.WebRootPath

Gdy IWebHostEnvironment.WebRootPath jest ustawiona wartość folderu innego niż wwwroot:

  • W środowisku projektowym zasoby statyczne znajdujące się zarówno w programie , jak wwwroot i zaktualizowane IWebHostEnvironment.WebRootPath są obsługiwane z witryny wwwroot.
  • W dowolnym środowisku innym niż programowanie zduplikowane zasoby statyczne są obsługiwane ze zaktualizowanego IWebHostEnvironment.WebRootPath folderu.

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 zwracaniu środowiska deweloperskiego wwwroot/Index.html
  • W dowolnym środowisku innym niż zwrot programowania wwwroot-custom/Index.html

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

  • Usuń zduplikowane nazwane zasoby w pliku wwwroot.

  • Ustaw "ASPNETCORE_ENVIRONMENT" wartość na Properties/launchSettings.json 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.

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 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

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

Domyślne szablony aplikacji internetowej wywołają metodę UseStaticFiles w Program.cspliku , która 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 bez UseStaticFiles parametrów oznacza pliki w katalogu głównym sieci Web jako możliwe. Następujące odwołania wwwroot/images/MyImage.jpgdo znaczników:

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

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

Obsługa 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 red-rose.jpg pliku, konfigurując oprogramowanie pośredniczące pliku statycznego 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 obsługi red-rose.jpg pliku.

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

<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 plików statycznych obsługujących 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 są wywoływane UseStaticFiles przed wywołaniem metody UseAuthorization. Większość aplikacji jest zgodnie z tym wzorcem. Po wywołaniu oprogramowania pośredniczącego plików statycznych przed oprogramowaniem pośredniczącym autoryzacji:

  • W plikach statycznych nie są wykonywane kontrole autoryzacji.
  • Pliki statyczne obsługiwane przez oprogramowanie pośredniczące 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 zasady autoryzacji rezerwowej.
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] autoryzacji lub [Authorize(PolicyName="MyPolicy")] użyj ich, a nie 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 katalogami wwwroot i dostępnymi dla oprogramowania pośredniczącego plików statycznych.
  • Za pomocą metody akcji, do której jest stosowana autoryzacja FileResult i zwraca obiekt:
[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

AddDirectoryBrowserdodaje 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 bez wwwroot konieczności uwzględnienia nazwy pliku przez adres 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ływana przed UseStaticFiles udostępnieniem pliku domyślnego. UseDefaultFiles jest autorem adresu URL, który nie obsługuje pliku.

Za pomocą polecenia UseDefaultFilesżądania do folderu w wwwroot wyszukiwaniu:

  • 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 element musi być wywoływany, EnableDirectoryBrowsing gdy wartość właściwości to true.

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

Identyfikator URI Response
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 wykonaj przekierowanie po stronie klienta z docelowego identyfikatora URI bez / końcowego identyfikatora URI z końcowym /identyfikatorem URI. 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 RedirectToAppendTrailingSlash 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 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">

UseStaticFilesi UseFileServer domyślnie do dostawcy plików wskazującego wartość .wwwroot Dodatkowe wystąpienia UseStaticFiles programu i UseFileServer mogą być udostępniane innym dostawcom plików w celu udostępniania plików z innych lokalizacji. Poniższy przykład wywołuje dwa razy, UseStaticFiles aby obsługiwać pliki z obu wwwroot elementów 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 może wyciekać tajemnice. Wyłączenie przeglądania katalogów w środowisku produkcyjnym jest zdecydowanie zalecane. Dokładnie sprawdź, które katalogi są włączone za pośrednictwem programu 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 zawartości uwidocznionej UseDirectoryBrowser UseStaticFiles i podlegają ograniczeniom poufności i znaków wielkości liter w podstawowym systemie plików. Na przykład system Windows nie uwzględnia wielkości liter, ale systemy macOS i Linux nie są.

  • ASP.NET Core aplikacje hostowane w usługach IIS używają modułu podstawowego ASP.NET 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 ma szans na obsługę żą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.

Obsługa plików poza witryną wwwroot przez zaktualizowanie elementu IWebHostEnvironment.WebRootPath

Gdy IWebHostEnvironment.WebRootPath jest ustawiona wartość folderu innego niż wwwroot:

  • W środowisku projektowym zasoby statyczne znajdujące się zarówno w programie , jak wwwroot i zaktualizowane IWebHostEnvironment.WebRootPath są obsługiwane z witryny wwwroot.
  • W dowolnym środowisku innym niż programowanie zduplikowane zasoby statyczne są obsługiwane ze zaktualizowanego IWebHostEnvironment.WebRootPath folderu.

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 zwracaniu środowiska deweloperskiego wwwroot/Index.html
  • W dowolnym środowisku innym niż zwrot programowania wwwroot-custom/Index.html

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

  • Usuń zduplikowane nazwane zasoby w pliku wwwroot.

  • Ustaw "ASPNETCORE_ENVIRONMENT" wartość na Properties/launchSettings.json 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 sieci Web.

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łają metodę UseStaticFiles w Startup.Configurepliku , która 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 bez UseStaticFiles parametrów oznacza pliki w katalogu głównym sieci Web jako możliwe. Następujące odwołania wwwroot/images/MyImage.jpgdo znaczników:

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

W poprzednim kodzie znak ~/ tyldy wskazuje katalog główny sieci Web.

Obsługa 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 red-rose.jpg pliku, konfigurując oprogramowanie pośredniczące pliku statycznego 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 https://<hostname>/StaticFiles/images/red-rose.jpg obsługi red-rose.jpg pliku.

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

<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 pliku statycznego obsługującego z katalogu głównego sieci Web następujący kod ustawia Cache-Control 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 są wywoływane UseStaticFiles przed wywołaniem metody UseAuthorization. Większość aplikacji jest zgodnie z tym wzorcem. Po wywołaniu oprogramowania pośredniczącego plików statycznych przed oprogramowaniem pośredniczącym autoryzacji:

  • W plikach statycznych nie są wykonywane kontrole autoryzacji.
  • Pliki statyczne obsługiwane przez oprogramowanie pośredniczące 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 zasady autoryzacji rezerwowej.
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 z zastosowanym atrybutem [AllowAnonymous] autoryzacji lub [Authorize(PolicyName="MyPolicy")] użyj ich, a nie 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 katalogami wwwroot i dostępnymi dla oprogramowania pośredniczącego plików statycznych.
  • Za pomocą metody akcji, do której jest stosowana autoryzacja FileResult i zwraca obiekt:
[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 bez wwwroot konieczności uwzględnienia nazwy pliku przez adres URL żądania, 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ływana przed UseStaticFiles udostępnieniem pliku domyślnego. UseDefaultFiles jest autorem adresu URL, który nie obsługuje pliku.

Za pomocą polecenia UseDefaultFilesżądania do folderu w wwwroot wyszukiwaniu:

  • 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 powyższy kod:

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 powyższy kod:

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 element musi być wywoływany, EnableDirectoryBrowsing gdy wartość właściwości to true.

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

Identyfikator URI Response
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 wykonaj przekierowanie po stronie klienta z docelowego identyfikatora URI bez / końcowego identyfikatora URI z końcowym /identyfikatorem URI. 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"
});

Poniższy kod przedstawia Startup.Configure powyższy kod:

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, 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:

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

Poniższy kod przedstawia Startup.Configure powyższy kod:

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

UseStaticFilesi UseFileServer domyślnie do dostawcy plików wskazującego wartość .wwwroot Dodatkowe wystąpienia UseStaticFiles programu i UseFileServer mogą być udostępniane innym dostawcom plików w celu udostępniania plików 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 może wyciekać tajemnice. Wyłączenie przeglądania katalogów w środowisku produkcyjnym jest zdecydowanie zalecane. Dokładnie sprawdź, które katalogi są włączone za pośrednictwem programu 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 zawartości uwidocznionej UseDirectoryBrowser UseStaticFiles i podlegają ograniczeniom poufności i znaków wielkości liter w podstawowym systemie plików. Na przykład system Windows nie uwzględnia wielkości liter, ale systemy macOS i Linux nie są.

  • ASP.NET Core aplikacje hostowane w usługach IIS używają modułu podstawowego ASP.NET 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 ma szans na obsługę żą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.

Dodatkowe zasoby