Freigeben über


Statische Dateien in ASP.NET Core

Hinweis

Dies ist nicht die neueste Version dieses Artikels. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Warnung

Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der Supportrichtlinie für .NET und .NET Core. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Wichtig

Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.

Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Von Rick Anderson

Bei statischen Dateien wie HTML, CSS, Images und JavaScript handelt es sich um Objekte, die Clients von einer ASP.NET Core-App standardmäßig direkt bereitgestellt werden.

Anleitungen zu statischen Dateien in Blazor, die die Anleitungen in diesem Artikel ergänzen oder ersetzen, finden Sie unter Statische Dateien in ASP.NET Core-Blazor.

Bereitstellen statischer Dateien

Statische Dateien werden im Webstammverzeichnis des Projekts gespeichert. Das Standardverzeichnis lautet {content root}/wwwroot, kann jedoch mit der Methode UseWebRoot geändert werden. Weitere Informationen finden Sie unter Inhaltsstammverzeichnis und Webstammverzeichnis.

Die Methode CreateBuilder legt das Inhaltsstammverzeichnis auf das aktuelle Verzeichnis fest:

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

Auf statische Dateien kann über einen Pfad relativ zum Webstammverzeichnis zugegriffen werden. Die Webanwendung-Projektvorlagen verfügen beispielsweise über mehrere Ordner innerhalb des Ordners wwwroot:

  • wwwroot
    • css
    • js
    • lib

Betrachten Sie eine App mit der wwwroot/images/MyImage.jpg-Datei. Das URI-Format für den Zugriff auf eine Datei im images-Ordner ist https://<hostname>/images/<image_file_name>. Beispiel: https://localhost:5001/images/MyImage.jpg

MapStaticAssets

Das Erstellen von leistungsfähigen Web-Apps erfordert die Optimierung der Ressourcenübermittlung an den Browser. Mögliche Optimierungen sind:

  • Eine bestimmte Ressource wird einmal bereitgestellt, bis sich die Datei ändert oder der Browser seinen Cache leert. Legen Sie den ETag-Header fest.
  • Es wird verhindert, dass der Browser alte oder veraltete Ressourcen verwendet, nachdem eine Anwendung aktualisiert wurde. Legen Sie den Header Zuletzt geändert fest.
  • Legen Sie den richtigen Zwischenspeicherungsheader fest.
  • Verwenden Sie die Zwischenspeicherungs-Middleware.
  • Stellen Sie wenn möglich komprimierte Versionen der Ressourcen bereit.
  • Verwenden Sie einen CDN, um die Ressourcen näher an die Benutzerin oder den Benutzer zu bringen.
  • Es minimiert die Größe der Ressourcen, die dem Browser zur Verfügung gestellt werden. Diese Optimierung beinhaltet keine Minimierung.

MapStaticAssets sind Routingendpunktkonventionen, die die Übermittlung statischer Objekte in einer App optimieren. Sie ist für alle UI-Frameworks geeignet, einschließlich Blazor, Razor Pages und MVC.

UseStaticFiles dient auch statischen Dateien, bietet aber nicht das gleiche Maß an Optimierung wie MapStaticAssets. Einen Vergleich von UseStaticFiles und MapStaticAssets finden Sie unter Optimierung der Bereitstellung statischer Web-Assets .

Verarbeiten von Dateien im Webstammverzeichnis

Mit den Standard-Webappvorlagen wird die MapStaticAssets-Methode in Program.cs aufgerufen, die die Verarbeitung statischer Dateien ermöglicht:

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

Die parameterlose Überladung der Methode UseStaticFiles markiert die Dateien im Webstammverzeichnis als bereitstellbar. Folgendes Markup verweist auf wwwroot/images/MyImage.jpg:

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

Im vorstehenden Markup verweist die Tilde (~) auf den Webstamm.

Bereitstellen von Dateien außerhalb des Webstammverzeichnisses

Erwägen Sie eine Verzeichnishierarchie, bei der sich die bereitzustellenden statischen Dateien außerhalb des Webstammverzeichnisses befinden:

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

Über eine Anforderung kann auf die Datei red-rose.jpg zugegriffen werden, indem die Middleware für statische Dateien wie folgt konfiguriert wird:

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

Im vorangehenden Code wird die MyStaticFiles-Verzeichnishierarchie öffentlich über das URI-Segment StaticFiles verfügbar gemacht. Eine Anforderung an https://<hostname>/StaticFiles/images/red-rose.jpg dient der red-rose.jpg-Datei.

Folgendes Markup verweist auf MyStaticFiles/images/red-rose.jpg:

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

Informationen zum Verarbeiten von Dateien aus mehreren Speicherorten finden Sie unter Bereitstellen von Dateien aus mehreren Speicherorten.

Festlegen von HTTP-Antwortheadern

Mit einem StaticFileOptions-Objekt können HTTP-Antwortheader festgelegt werden. Neben der Konfiguration statischer, über den Webstamm bereitgestellter Dateien wird mit dem folgenden Code der Cache-Control-Header festgelegt:

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

Der vorangehende Code macht statische Dateien im lokalen Cache eine Woche lang öffentlich zugänglich.

Autorisierung statischer Dateien

Die ASP.NET Core-Vorlagen rufen MapStaticAssets vor UseAuthorization auf. Die meisten Apps folgen diesem Muster. Wenn die Middleware für statische Dateien vor der Autorisierungsmiddleware aufgerufen wird, gilt Folgendes:

  • In den statischen Dateien werden keine Autorisierungsüberprüfungen durchgeführt.
  • Statische Dateien, die von der Middleware für statische Dateien bereitgestellt werden – wie beispielsweise diejenigen unter wwwroot – sind öffentlich zugänglich.

So stellen Sie statische Dateien basierend auf Autorisierung bereit:

  • Speichern Sie sie außerhalb von wwwroot.
  • Rufen Sie UseStaticFiles nach dem Aufruf von UseAuthorization auf, und geben Sie einen Pfad an.
  • Legen Sie die Autorisierungsrichtlinie für Fallbacks fest.
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();

Im vorstehenden Code erfordert die Richtlinie für die Fallbackautorisierung, dass alle Benutzer authentifiziert werden müssen. Endpunkte wie Controller, Razor Pages usw., die eigene Autorisierungsanforderungen angeben, verwenden die Autorisierungsrichtlinie für Fallbacks nicht. Beispielsweise verwenden Razor Pages, Controller oder Aktionsmethoden mit [AllowAnonymous] oder [Authorize(PolicyName="MyPolicy")] das angewendete Autorisierungsattribut anstelle der Autorisierungsrichtlinie für Fallbacks.

RequireAuthenticatedUser fügt der aktuellen Instanz DenyAnonymousAuthorizationRequirement hinzu. Dadurch wird die Authentifizierung des aktuellen Benutzers erzwungen.

Statische Ressourcen unter wwwroot sind öffentlich zugänglich, weil die Middleware für statische Dateien (app.UseStaticFiles();) vor UseAuthentication aufgerufen wird. Statische Ressourcen im MyStaticFiles-Ordner erfordern eine Authentifizierung. Dies wird im Beispielcode veranschaulicht.

Eine Alternative zum Bereitstellen von Dateien basierend auf Autorisierung ist folgendes Verfahren:

  • Speichern Sie sie außerhalb von wwwroot sowie außerhalb sämtlicher Verzeichnisse, auf die die Middleware für statische Dateien zugreifen kann.

  • Stellen Sie sie über eine Aktionsmethode bereit, für die die Autorisierung gilt, und geben Sie ein FileResult-Objekt zurück:

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

Für den vorherigen Ansatz ist eine Seite oder ein Endpunkt pro Datei erforderlich. Der folgende Code gibt Dateien zurück oder lädt Dateien für authentifizierte Benutzer*innen hoch:

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

IFormFile in dem vorangegangenen Beispiel verwendet einen Speicherpuffer für das Hochladen. Für die Verarbeitung großer Dateien verwenden Sie Streaming. Siehe Hochladen von großen Dateien mittels Streaming.

Das vollständige Beispiel finden Sie im GitHub-Ordner StaticFileAuth.

Verzeichnissuche

Die Verzeichnissuche ermöglicht die Verzeichnisauflistung in angegebenen Verzeichnissen.

Die Verzeichnissuche ist aus Sicherheitsgründen standardmäßig deaktiviert. Weitere Informationen finden Sie unter Sicherheitsüberlegungen für statische Dateien.

Aktivieren Sie die Verzeichnissuche mit AddDirectoryBrowser und 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();

Der vorangehende Code ermöglicht die Verzeichnissuche im Ordner wwwroot/images über die URL https://<hostname>/MyImages mit Links zu den einzelnen Dateien und Ordnern:

Verzeichnissuche

AddDirectoryBrowser fügt Dienste hinzu, die von der Middleware für die Verzeichnissuche benötigt werden, einschließlich HtmlEncoder. Diese Dienste können auch mit anderen Aufrufen hinzugefügt werden, z. B. AddRazorPages, aber wir empfehlen den Aufruf von AddDirectoryBrowser, um sicherzustellen, dass die Dienste in allen Apps hinzugefügt werden.

Bereitstellen von Standarddokumenten

Durch das Festlegen einer Standardseite wird Besuchern ein Ausgangspunkt auf einer Website bereitgestellt. Rufen Sie die UseDefaultFiles-Methode auf, um eine Standarddatei aus wwwroot zu stellen, ohne dass die Anforderungs-URL im Dateinamen enthalten sein muss:

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 muss vor UseStaticFiles aufgerufen werden, damit die Standarddatei bereitgestellt wird. UseDefaultFiles ist ein URL-Rewriter, der die Datei nicht verarbeiten kann.

Bei UseDefaultFiles werden bei Anforderungen an einen Ordner in wwwroot folgende Dateien durchsucht:

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

Die erste in der Liste gefundene Datei wird bereitgestellt, als wäre die Anforderung im Dateinamen enthalten. Die Browser-URL spiegelt weiterhin den angeforderten URI wider. In der Beispielanwendung wird zum Beispiel bei einer Anfrage an https://localhost:<port>/def/ default.html von wwwroot/def bedient.

Mit dem folgenden Code wird der Standarddateiname in mydefault.html geändert:

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 für Standarddokumente

In UseFileServer werden die Funktionen von UseStaticFiles, UseDefaultFiles und (optional) UseDirectoryBrowser miteinander kombiniert.

Rufen Sie app.UseFileServer auf, um die Bereitstellung statischer Dateien und der Standarddatei zu aktivieren. Die Verzeichnissuche ist nicht aktiviert:

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

Mit dem folgenden Code wird die Bereitstellung statischer Dateien, der Standarddatei und der Verzeichnissuche aktiviert:

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

Betrachten Sie die folgende Verzeichnishierarchie:

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

Mit dem folgenden Code wird die Bereitstellung statischer Dateien, der Standarddatei und der Verzeichnissuche von MyStaticFiles aktiviert:

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 muss aufgerufen werden, wenn der EnableDirectoryBrowsing-Eigenschaftswert true lautet.

Unter Verwendung der vorstehenden Dateihierarchie und des vorangehenden Codes werden URLs wie folgt aufgelöst:

URI Antwort
https://<hostname>/StaticFiles/images/MyImage.jpg MyStaticFiles/images/MyImage.jpg
https://<hostname>/StaticFiles Verzeichnisauflistung
https://<hostname>/StaticFiles/defaultFiles MyStaticFiles/defaultFiles/default.html
https://<hostname>/StaticFiles/defaultFiles/image3.png MyStaticFiles/defaultFiles//image3.png

Wenn im Verzeichnis MyStaticFiles keine Datei mit Standardnamen vorhanden ist, gibt https://<hostname>/StaticFiles die Verzeichnisliste mit klickbaren Links zurück:

Liste der statischen Dateien

UseDefaultFiles und UseDirectoryBrowser führen eine clientseitige Umleitung vom Ziel-URI ohne nachgestellten / zum Ziel-URI mit nachgestelltem / durch. Beispielsweise von https://<hostname>/StaticFiles zu https://<hostname>/StaticFiles/. Relative URLs im Verzeichnis StaticFiles gelten ohne nachstehenden Schrägstrich (/) als ungültig, sofern nicht die RedirectToAppendTrailingSlash-Option von DefaultFilesOptions verwendet wird.

FileExtensionContentTypeProvider

Die FileExtensionContentTypeProvider-Klasse enthält eine Zuordnungs-Eigenschaft, die als Zuordnung von Dateierweiterungen zu MIME-Inhaltstypen dient. Im folgenden Beispiel werden mehrere Dateierweiterungen bekannten MIME-Typen zugeordnet. Die Erweiterung .rtf wird ersetzt, und .mp4 wird entfernt:

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

Weitere Informationen finden Sie unter MIME-Inhaltstypen.

Inhaltstypen, die vom Standard abweichen

Die Middleware für statische Dateien erkennt fast 400 bekannte Dateiinhaltstypen. Wenn ein Benutzer eine Datei mit einem unbekannten Dateityp anfordert, übergibt die Middleware für statische Dateien die Anforderung an die nächste Middleware in der Pipeline. Wenn keine Middleware die Anforderung verarbeitet, wird die Meldung 404 Nicht gefunden zurückgegeben. Wenn die Verzeichnissuche aktiviert ist, wird ein Link zur Datei in einer Verzeichnisliste angezeigt.

Mit dem folgenden Code wird die Bereitstellung unbekannter Typen aktiviert und die unbekannte Datei als Image gerendert:

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

Mit dem vorangehenden Code wird eine Anforderung für eine Datei mit unbekanntem Inhaltstyp als Image zurückgegeben.

Warnung

Die Aktivierung von ServeUnknownFileTypes stellt ein Sicherheitsrisiko dar. Diese Eigenschaft ist standardmäßig deaktiviert, von einer Verwendung wird abgeraten. FileExtensionContentTypeProvider bietet eine sicherere Alternative für die Bereitstellung von Dateien mit vom Standard abweichenden Erweiterungen.

Bereitstellen von Dateien aus mehreren Speicherorten

Beachten Sie die folgende Razor Seite, welche die /MyStaticFiles/image3.png Datei anzeigt:

@page

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

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

Bei UseStaticFiles und UseFileServer zeigt der Dateianbieter standardmäßig auf wwwroot. Weitere Instanzen von UseStaticFiles und UseFileServer können mit anderen Dateianbietern bereitgestellt werden, um Dateien von anderen Speicherorten bereitzustellen. Das folgende Beispiel ruft UseStaticFiles zweimal auf, um Dateien aus wwwroot und MyStaticFiles zu verarbeiten:

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

Unter Verwendung des vorherigen Codes:

  • Die /MyStaticFiles/image3.png Datei wird angezeigt.
  • Die Bildtag-Hilfsprogramme AppendVersion werden nicht angewendet, da die Tag-Hilfsprogramme abhängig von WebRootFileProvider sind. WebRootFileProvider wurde nicht aktualisiert, den MyStaticFiles Ordner zu beinhalten.

Der folgende Code aktualisiert WebRootFileProvider, wodurch das Bildtag-Hilfsprogramm eine Version bereitstellen kann:

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

Hinweis

Der zuvor beschriebene Ansatz gilt für Razor Pages und MVC-Apps. Anleitungen, die für Blazor Web App gelten, finden Sie unter Statische Dateien in ASP.NET Core-Blazor.

Sicherheitsüberlegungen für statische Dateien

Warnung

UseDirectoryBrowser und UseStaticFiles können Geheimnisse preisgeben. Eine Deaktivierung der Verzeichnissuche in der Produktionsumgebung wird dringend empfohlen. Überprüfen Sie sorgfältig, welche Verzeichnisse über UseStaticFiles oder UseDirectoryBrowser aktiviert wurden. Das gesamte Verzeichnis und die zugehörigen Unterverzeichnisse werden öffentlich zugänglich gemacht. Speichern Sie Dateien, die für eine Bereitstellung in der Öffentlichkeit geeignet sind, in einem dafür vorgesehenen Verzeichnis wie z.B. <content_root>/wwwroot. Trennen Sie diese Dateien von MVC-Ansichten, Razor Pages, Konfigurationsdateien usw.

  • Die URLs für Inhalte, die mit UseDirectoryBrowser, UseStaticFiles und MapStaticAssets angezeigt werden, unterliegen der Groß-/Kleinschreibung und den Zeichenbeschränkungen des zugrunde liegenden Dateisystems. Bei Windows wird die Groß-/Kleinschreibung beispielsweise nicht beachtet, jedoch bei macOS und Linux.

  • In IIS gehostete ASP.NET Core-Apps leiten über das ASP.NET Core-Modul alle Anforderungen an die App weiter, darunter die Anforderungen von statischen Dateien. Der IIS-Handler für statische Dateien wird nicht verwendet und hat keine Möglichkeit, Anforderungen zu verarbeiten.

  • Führen Sie im IIS-Manager die folgenden Schritte aus, um den statischen IIS-Dateihandler auf Server- oder Website-Ebene zu entfernen:

    1. Navigieren Sie zum Feature Module.
    2. Wählen Sie StaticFileModule aus der Liste aus.
    3. Klicken Sie in der Randleiste Aktionen auf Entfernen.

Warnung

Wenn der statische IIS-Dateihandler aktiviert ist und das ASP.NET Core-Modul falsch konfiguriert wurde, werden statische Dateien bereitgestellt. Dies geschieht beispielsweise, wenn die Datei web.config nicht bereitgestellt worden ist.

  • Platzieren Sie Codedateien einschließlich .cs und .cshtml außerhalb des Webstammverzeichnisses des App-Projekts. Aus diesem Grund wird eine logische Trennung zwischen den clientseitigen Inhalten der App und dem serverbasierten Code erschaffen. Dadurch wird verhindert, dass serverseitiger Code aufgedeckt wird.

Bedienen Sie Dateien außerhalb von wwwroot, indem Sie IWebHostEnvironment.WebRootPath aktualisieren

Wenn IWebHostEnvironment.WebRootPath auf einen anderen Ordner als wwwroot festgelegt ist:

  • In der Entwicklungsumgebung werden statische Ressourcen, die sich sowohl unter wwwroot als auch dem aktualisierten IWebHostEnvironment.WebRootPath befinden, von wwwroot bedient.
  • In jeder anderen Umgebung als der Entwicklungsumgebung werden doppelt vorhandene statische Ressourcen aus dem aktualisierten IWebHostEnvironment.WebRootPath-Ordner bereitgestellt.

Betrachten Sie eine Web-App, die mit der leeren Webvorlage erstellt wurde:

  • Sie enthält eine Datei Index.html in wwwroot und wwwroot-custom.

  • Mit der folgenden aktualisierten Program.cs-Datei, die WebRootPath = "wwwroot-custom" festlegt:

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

Im vorhergehenden Code bewirken Anforderungen an / Folgendes:

  • In der Entwicklungsumgebung wird wwwroot/Index.html zurückgegeben
  • In jeder anderen Umgebung als der Entwicklungsumgebung wird wwwroot-custom/Index.html zurückgegeben

Verwenden Sie eine der folgenden Ansätze, um sicherzustellen, dass Ressourcen aus wwwroot-custom zurückgegeben werden:

  • Löschen Sie doppelte benannte Ressourcen in wwwroot.

  • Legen Sie "ASPNETCORE_ENVIRONMENT" in Properties/launchSettings.json auf einen beliebigen anderen Wert als "Development" fest.

  • Deaktivieren Sie statische Webressourcen vollständig, indem Sie <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled> in der Projektdatei festlegen. WARNUNG: Durch das Deaktivieren statischer Webressourcen werden die Razor-Klassenbibliotheken deaktiviert.

  • Fügen Sie der Projektdatei die folgende XML hinzu:

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

Der folgende Code aktualisiert IWebHostEnvironment.WebRootPath auf einen nicht auf die Entwicklung bezogenen Wert, der garantiert, dass doppelte Inhalte aus wwwroot-custom anstelle von wwwroot zurückgegeben werden:

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

Zusätzliche Ressourcen

Von Rick Anderson

Bei statischen Dateien wie HTML, CSS, Images und JavaScript handelt es sich um Objekte, die Clients von einer ASP.NET Core-App standardmäßig direkt bereitgestellt werden.

Bereitstellen statischer Dateien

Statische Dateien werden im Webstammverzeichnis des Projekts gespeichert. Das Standardverzeichnis lautet {content root}/wwwroot, kann jedoch mit der Methode UseWebRoot geändert werden. Weitere Informationen finden Sie unter Inhaltsstammverzeichnis und Webstammverzeichnis.

Die Methode CreateBuilder legt das Inhaltsstammverzeichnis auf das aktuelle Verzeichnis fest:

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

Auf statische Dateien kann über einen Pfad relativ zum Webstammverzeichnis zugegriffen werden. Die Webanwendung-Projektvorlagen verfügen beispielsweise über mehrere Ordner innerhalb des Ordners wwwroot:

  • wwwroot
    • css
    • js
    • lib

Erstellen Sie ggf. den wwwroot/images-Ordner, und fügen Sie die Datei wwwroot/images/MyImage.jpg hinzu. Das URI-Format für den Zugriff auf eine Datei im images-Ordner ist https://<hostname>/images/<image_file_name>. Beispiel: https://localhost:5001/images/MyImage.jpg

Verarbeiten von Dateien im Webstammverzeichnis

Mit den Standard-Webappvorlagen wird die UseStaticFiles-Methode in Program.cs aufgerufen, die die Verarbeitung statischer Dateien ermöglicht:

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

Die parameterlose Überladung der Methode UseStaticFiles markiert die Dateien im Webstammverzeichnis als bereitstellbar. Folgendes Markup verweist auf wwwroot/images/MyImage.jpg:

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

Im vorstehenden Markup verweist die Tilde (~) auf den Webstamm.

Bereitstellen von Dateien außerhalb des Webstammverzeichnisses

Erwägen Sie eine Verzeichnishierarchie, bei der sich die bereitzustellenden statischen Dateien außerhalb des Webstammverzeichnisses befinden:

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

Über eine Anforderung kann auf die Datei red-rose.jpg zugegriffen werden, indem die Middleware für statische Dateien wie folgt konfiguriert wird:

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

Im vorangehenden Code wird die MyStaticFiles-Verzeichnishierarchie öffentlich über das URI-Segment StaticFiles verfügbar gemacht. Eine Anforderung an https://<hostname>/StaticFiles/images/red-rose.jpg dient der red-rose.jpg-Datei.

Folgendes Markup verweist auf MyStaticFiles/images/red-rose.jpg:

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

Informationen zum Verarbeiten von Dateien aus mehreren Speicherorten finden Sie unter Bereitstellen von Dateien aus mehreren Speicherorten.

Festlegen von HTTP-Antwortheadern

Mit einem StaticFileOptions-Objekt können HTTP-Antwortheader festgelegt werden. Neben der Konfiguration statischer, über den Webstamm bereitgestellter Dateien wird mit dem folgenden Code der Cache-Control-Header festgelegt:

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

Der vorstehende Code macht statische Dateien im lokalen Cache eine Woche lang (604800 Sekunden) öffentlich zugänglich.

Autorisierung statischer Dateien

Die ASP.NET Core-Vorlagen rufen UseStaticFiles vor UseAuthorization auf. Die meisten Apps folgen diesem Muster. Wenn die Middleware für statische Dateien vor der Autorisierungsmiddleware aufgerufen wird, gilt Folgendes:

  • In den statischen Dateien werden keine Autorisierungsüberprüfungen durchgeführt.
  • Statische Dateien, die von der Middleware für statische Dateien bereitgestellt werden – wie beispielsweise diejenigen unter wwwroot – sind öffentlich zugänglich.

So stellen Sie statische Dateien basierend auf Autorisierung bereit:

  • Speichern Sie sie außerhalb von wwwroot.
  • Rufen Sie UseStaticFiles nach dem Aufruf von UseAuthorization auf, und geben Sie einen Pfad an.
  • Legen Sie die Autorisierungsrichtlinie für Fallbacks fest.
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();

Im vorstehenden Code erfordert die Richtlinie für die Fallbackautorisierung, dass alle Benutzer authentifiziert werden müssen. Endpunkte wie Controller, Razor Pages usw., die eigene Autorisierungsanforderungen angeben, verwenden die Autorisierungsrichtlinie für Fallbacks nicht. Beispielsweise verwenden Razor Pages, Controller oder Aktionsmethoden mit [AllowAnonymous] oder [Authorize(PolicyName="MyPolicy")] das angewendete Autorisierungsattribut anstelle der Autorisierungsrichtlinie für Fallbacks.

RequireAuthenticatedUser fügt der aktuellen Instanz DenyAnonymousAuthorizationRequirement hinzu. Dadurch wird die Authentifizierung des aktuellen Benutzers erzwungen.

Statische Ressourcen unter wwwroot sind öffentlich zugänglich, weil die Middleware für statische Dateien (app.UseStaticFiles();) vor UseAuthentication aufgerufen wird. Statische Ressourcen im MyStaticFiles-Ordner erfordern eine Authentifizierung. Dies wird im Beispielcode veranschaulicht.

Eine Alternative zum Bereitstellen von Dateien basierend auf Autorisierung ist folgendes Verfahren:

  • Speichern Sie sie außerhalb von wwwroot sowie außerhalb sämtlicher Verzeichnisse, auf die die Middleware für statische Dateien zugreifen kann.

  • Stellen Sie sie über eine Aktionsmethode bereit, für die die Autorisierung gilt, und geben Sie ein FileResult-Objekt zurück:

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

Für den vorherigen Ansatz ist eine Seite oder ein Endpunkt pro Datei erforderlich. Der folgende Code gibt Dateien zurück oder lädt Dateien für authentifizierte Benutzer*innen hoch:

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

Das vollständige Beispiel finden Sie im GitHub-Ordner StaticFileAuth.

Verzeichnissuche

Die Verzeichnissuche ermöglicht die Verzeichnisauflistung in angegebenen Verzeichnissen.

Die Verzeichnissuche ist aus Sicherheitsgründen standardmäßig deaktiviert. Weitere Informationen finden Sie unter Sicherheitsüberlegungen für statische Dateien.

Aktivieren Sie die Verzeichnissuche mit AddDirectoryBrowser und 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();

Der vorangehende Code ermöglicht die Verzeichnissuche im Ordner wwwroot/images über die URL https://<hostname>/MyImages mit Links zu den einzelnen Dateien und Ordnern:

Verzeichnissuche

AddDirectoryBrowser fügt Dienste hinzu, die von der Middleware für die Verzeichnissuche benötigt werden, einschließlich HtmlEncoder. Diese Dienste können auch mit anderen Aufrufen hinzugefügt werden, z. B. AddRazorPages, aber wir empfehlen den Aufruf von AddDirectoryBrowser, um sicherzustellen, dass die Dienste in allen Apps hinzugefügt werden.

Bereitstellen von Standarddokumenten

Durch das Festlegen einer Standardseite wird Besuchern ein Ausgangspunkt auf einer Website bereitgestellt. Rufen Sie die UseDefaultFiles-Methode auf, um eine Standarddatei aus wwwroot zu stellen, ohne dass die Anforderungs-URL im Dateinamen enthalten sein muss:

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 muss vor UseStaticFiles aufgerufen werden, damit die Standarddatei bereitgestellt wird. UseDefaultFiles ist ein URL-Rewriter, der die Datei nicht verarbeiten kann.

Bei UseDefaultFiles werden bei Anforderungen an einen Ordner in wwwroot folgende Dateien durchsucht:

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

Die erste in der Liste gefundene Datei wird bereitgestellt, als wäre die Anforderung im Dateinamen enthalten. Die Browser-URL spiegelt weiterhin den angeforderten URI wider.

Mit dem folgenden Code wird der Standarddateiname in mydefault.html geändert:

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 für Standarddokumente

In UseFileServer werden die Funktionen von UseStaticFiles, UseDefaultFiles und (optional) UseDirectoryBrowser miteinander kombiniert.

Rufen Sie app.UseFileServer auf, um die Bereitstellung statischer Dateien und der Standarddatei zu aktivieren. Die Verzeichnissuche ist nicht aktiviert:

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

Mit dem folgenden Code wird die Bereitstellung statischer Dateien, der Standarddatei und der Verzeichnissuche aktiviert:

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

Betrachten Sie die folgende Verzeichnishierarchie:

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

Mit dem folgenden Code wird die Bereitstellung statischer Dateien, der Standarddatei und der Verzeichnissuche von MyStaticFiles aktiviert:

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 muss aufgerufen werden, wenn der EnableDirectoryBrowsing-Eigenschaftswert true lautet.

Unter Verwendung der vorstehenden Dateihierarchie und des vorangehenden Codes werden URLs wie folgt aufgelöst:

URI Antwort
https://<hostname>/StaticFiles/images/MyImage.jpg MyStaticFiles/images/MyImage.jpg
https://<hostname>/StaticFiles MyStaticFiles/default.html

Wenn im Verzeichnis MyStaticFiles keine Datei mit Standardnamen vorhanden ist, gibt https://<hostname>/StaticFiles die Verzeichnisliste mit klickbaren Links zurück:

Liste der statischen Dateien

UseDefaultFiles und UseDirectoryBrowser führen eine clientseitige Umleitung vom Ziel-URI ohne nachgestellten / zum Ziel-URI mit nachgestelltem / durch. Beispielsweise von https://<hostname>/StaticFiles zu https://<hostname>/StaticFiles/. Relative URLs im Verzeichnis StaticFiles gelten ohne nachstehenden Schrägstrich (/) als ungültig, sofern nicht die RedirectToAppendTrailingSlash-Option von DefaultFilesOptions verwendet wird.

FileExtensionContentTypeProvider

Die Klasse FileExtensionContentTypeProvider enthält eine Mappings-Eigenschaft, die als Zuordnung von Dateierweiterungen zu MIME-Inhaltstypen dient. Im folgenden Beispiel werden mehrere Dateierweiterungen bekannten MIME-Typen zugeordnet. Die Erweiterung .rtf wird ersetzt, und .mp4 wird entfernt:

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

Weitere Informationen finden Sie unter MIME-Inhaltstypen.

Inhaltstypen, die vom Standard abweichen

Die Middleware für statische Dateien erkennt fast 400 bekannte Dateiinhaltstypen. Wenn ein Benutzer eine Datei mit einem unbekannten Dateityp anfordert, übergibt die Middleware für statische Dateien die Anforderung an die nächste Middleware in der Pipeline. Wenn keine Middleware die Anforderung verarbeitet, wird die Meldung 404 Nicht gefunden zurückgegeben. Wenn die Verzeichnissuche aktiviert ist, wird ein Link zur Datei in einer Verzeichnisliste angezeigt.

Mit dem folgenden Code wird die Bereitstellung unbekannter Typen aktiviert und die unbekannte Datei als Image gerendert:

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

Mit dem vorangehenden Code wird eine Anforderung für eine Datei mit unbekanntem Inhaltstyp als Image zurückgegeben.

Warnung

Die Aktivierung von ServeUnknownFileTypes stellt ein Sicherheitsrisiko dar. Diese Eigenschaft ist standardmäßig deaktiviert, von einer Verwendung wird abgeraten. FileExtensionContentTypeProvider bietet eine sicherere Alternative für die Bereitstellung von Dateien mit vom Standard abweichenden Erweiterungen.

Bereitstellen von Dateien aus mehreren Speicherorten

Beachten Sie die folgende Razor Seite, welche die /MyStaticFiles/image3.png Datei anzeigt:

@page

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

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

Bei UseStaticFiles und UseFileServer zeigt der Dateianbieter standardmäßig auf wwwroot. Weitere Instanzen von UseStaticFiles und UseFileServer können mit anderen Dateianbietern bereitgestellt werden, um Dateien von anderen Speicherorten bereitzustellen. Das folgende Beispiel ruft UseStaticFiles zweimal auf, um Dateien aus wwwroot und MyStaticFiles zu verarbeiten:

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

Unter Verwendung des vorherigen Codes:

  • Die /MyStaticFiles/image3.png Datei wird angezeigt.
  • Die Bildtag-Hilfsprogramme AppendVersion werden nicht angewendet, da die Tag-Hilfsprogramme abhängig von WebRootFileProvider sind. WebRootFileProvider wurde nicht aktualisiert, den MyStaticFiles Ordner zu beinhalten.

Der folgende Code aktualisiert WebRootFileProvider, wodurch das Bildtag-Hilfsprogramm eine Version bereitstellen kann:

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

Hinweis

Der zuvor beschriebene Ansatz gilt für Razor Pages und MVC-Apps. Anleitungen, die für Blazor Web App gelten, finden Sie unter Statische Dateien in ASP.NET Core-Blazor.

Sicherheitsüberlegungen für statische Dateien

Warnung

UseDirectoryBrowser und UseStaticFiles können Geheimnisse aufdecken. Eine Deaktivierung der Verzeichnissuche in der Produktionsumgebung wird dringend empfohlen. Überprüfen Sie sorgfältig, welche Verzeichnisse über UseStaticFiles oder UseDirectoryBrowser aktiviert wurden. Das gesamte Verzeichnis und die zugehörigen Unterverzeichnisse werden öffentlich zugänglich gemacht. Speichern Sie Dateien, die für eine Bereitstellung in der Öffentlichkeit geeignet sind, in einem dafür vorgesehenen Verzeichnis wie z.B. <content_root>/wwwroot. Trennen Sie diese Dateien von MVC-Ansichten, Razor Pages, Konfigurationsdateien usw.

  • Die URLs für Inhalte, die mit UseDirectoryBrowser und UseStaticFiles verfügbar gemacht wurden, unterliegen der Groß-/Kleinschreibung und den Zeichenbeschränkungen des zugrunde liegenden Dateisystems. Bei Windows wird die Groß-/Kleinschreibung beispielsweise nicht beachtet, jedoch bei macOS und Linux.

  • In IIS gehostete ASP.NET Core-Apps leiten über das ASP.NET Core-Modul alle Anforderungen an die App weiter, darunter die Anforderungen von statischen Dateien. Der IIS-Handler für statische Dateien wird nicht verwendet und hat keine Möglichkeit, Anforderungen zu verarbeiten.

  • Führen Sie im IIS-Manager die folgenden Schritte aus, um den statischen IIS-Dateihandler auf Server- oder Website-Ebene zu entfernen:

    1. Navigieren Sie zum Feature Module.
    2. Wählen Sie StaticFileModule aus der Liste aus.
    3. Klicken Sie in der Randleiste Aktionen auf Entfernen.

Warnung

Wenn der statische IIS-Dateihandler aktiviert ist und das ASP.NET Core-Modul falsch konfiguriert wurde, werden statische Dateien bereitgestellt. Dies geschieht beispielsweise, wenn die Datei web.config nicht bereitgestellt worden ist.

  • Platzieren Sie Codedateien einschließlich .cs und .cshtml außerhalb des Webstammverzeichnisses des App-Projekts. Aus diesem Grund wird eine logische Trennung zwischen den clientseitigen Inhalten der App und dem serverbasierten Code erschaffen. Dadurch wird verhindert, dass serverseitiger Code aufgedeckt wird.

Bedienen Sie Dateien außerhalb von wwwroot, indem Sie IWebHostEnvironment.WebRootPath aktualisieren

Wenn IWebHostEnvironment.WebRootPath auf einen anderen Ordner als wwwroot festgelegt ist:

  • In der Entwicklungsumgebung werden statische Ressourcen, die sich sowohl unter wwwroot als auch dem aktualisierten IWebHostEnvironment.WebRootPath befinden, von wwwroot bedient.
  • In jeder anderen Umgebung als der Entwicklungsumgebung werden doppelt vorhandene statische Ressourcen aus dem aktualisierten IWebHostEnvironment.WebRootPath-Ordner bereitgestellt.

Betrachten Sie eine Web-App, die mit der leeren Webvorlage erstellt wurde:

  • Sie enthält eine Datei Index.html in wwwroot und wwwroot-custom.

  • Mit der folgenden aktualisierten Program.cs-Datei, die WebRootPath = "wwwroot-custom" festlegt:

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

Im vorhergehenden Code bewirken Anforderungen an / Folgendes:

  • In der Entwicklungsumgebung wird wwwroot/Index.html zurückgegeben
  • In jeder anderen Umgebung als der Entwicklungsumgebung wird wwwroot-custom/Index.html zurückgegeben

Verwenden Sie eine der folgenden Ansätze, um sicherzustellen, dass Ressourcen aus wwwroot-custom zurückgegeben werden:

  • Löschen Sie doppelte benannte Ressourcen in wwwroot.

  • Legen Sie "ASPNETCORE_ENVIRONMENT" in Properties/launchSettings.json auf einen beliebigen anderen Wert als "Development" fest.

  • Deaktivieren Sie statische Webressourcen vollständig, indem Sie <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled> in der Projektdatei festlegen. WARNUNG: Durch das Deaktivieren statischer Webressourcen werden die Razor-Klassenbibliotheken deaktiviert.

  • Fügen Sie der Projektdatei den folgenden JSON-Code hinzu:

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

Der folgende Code aktualisiert IWebHostEnvironment.WebRootPath auf einen nicht auf die Entwicklung bezogenen Wert, der garantiert, dass doppelte Inhalte aus wwwroot-custom anstelle von wwwroot zurückgegeben werden:

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

Zusätzliche Ressourcen

Von Rick Anderson und Kirk Larkin

Bei statischen Dateien wie HTML, CSS, Images und JavaScript handelt es sich um Objekte, die Clients von einer ASP.NET Core-App standardmäßig direkt bereitgestellt werden.

Bereitstellen statischer Dateien

Statische Dateien werden im Webstammverzeichnis des Projekts gespeichert. Das Standardverzeichnis lautet {content root}/wwwroot, kann jedoch mit der Methode UseWebRoot geändert werden. Weitere Informationen finden Sie unter Inhaltsstammverzeichnis und Webstammverzeichnis.

Die Methode CreateBuilder legt das Inhaltsstammverzeichnis auf das aktuelle Verzeichnis fest:

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

Auf statische Dateien kann über einen Pfad relativ zum Webstammverzeichnis zugegriffen werden. Die Webanwendung-Projektvorlagen verfügen beispielsweise über mehrere Ordner innerhalb des Ordners wwwroot:

  • wwwroot
    • css
    • js
    • lib

Erstellen Sie ggf. den wwwroot/images-Ordner, und fügen Sie die Datei wwwroot/images/MyImage.jpg hinzu. Das URI-Format für den Zugriff auf eine Datei im images-Ordner ist https://<hostname>/images/<image_file_name>. Beispiel: https://localhost:5001/images/MyImage.jpg

Verarbeiten von Dateien im Webstammverzeichnis

Mit den Standard-Webappvorlagen wird die UseStaticFiles-Methode in Program.cs aufgerufen, die die Verarbeitung statischer Dateien ermöglicht:

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

Die parameterlose Überladung der Methode UseStaticFiles markiert die Dateien im Webstammverzeichnis als bereitstellbar. Folgendes Markup verweist auf wwwroot/images/MyImage.jpg:

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

Im vorstehenden Markup verweist die Tilde (~) auf den Webstamm.

Bereitstellen von Dateien außerhalb des Webstammverzeichnisses

Erwägen Sie eine Verzeichnishierarchie, bei der sich die bereitzustellenden statischen Dateien außerhalb des Webstammverzeichnisses befinden:

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

Über eine Anforderung kann auf die Datei red-rose.jpg zugegriffen werden, indem die Middleware für statische Dateien wie folgt konfiguriert wird:

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

Im vorangehenden Code wird die MyStaticFiles-Verzeichnishierarchie öffentlich über das URI-Segment StaticFiles verfügbar gemacht. Eine Anforderung an https://<hostname>/StaticFiles/images/red-rose.jpg dient der red-rose.jpg-Datei.

Folgendes Markup verweist auf MyStaticFiles/images/red-rose.jpg:

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

Informationen zum Verarbeiten von Dateien aus mehreren Speicherorten finden Sie unter Bereitstellen von Dateien aus mehreren Speicherorten.

Festlegen von HTTP-Antwortheadern

Mit einem StaticFileOptions-Objekt können HTTP-Antwortheader festgelegt werden. Neben der Konfiguration statischer, über den Webstamm bereitgestellter Dateien wird mit dem folgenden Code der Cache-Control-Header festgelegt:

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

Der vorstehende Code macht statische Dateien im lokalen Cache eine Woche lang (604800 Sekunden) öffentlich zugänglich.

Autorisierung statischer Dateien

Die ASP.NET Core-Vorlagen rufen UseStaticFiles vor UseAuthorization auf. Die meisten Apps folgen diesem Muster. Wenn die Middleware für statische Dateien vor der Autorisierungsmiddleware aufgerufen wird, gilt Folgendes:

  • In den statischen Dateien werden keine Autorisierungsüberprüfungen durchgeführt.
  • Statische Dateien, die von der Middleware für statische Dateien bereitgestellt werden – wie beispielsweise diejenigen unter wwwroot – sind öffentlich zugänglich.

So stellen Sie statische Dateien basierend auf Autorisierung bereit:

  • Speichern Sie sie außerhalb von wwwroot.
  • Rufen Sie UseStaticFiles nach dem Aufruf von UseAuthorization auf, und geben Sie einen Pfad an.
  • Legen Sie die Autorisierungsrichtlinie für Fallbacks fest.
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();

Im vorstehenden Code erfordert die Richtlinie für die Fallbackautorisierung, dass alle Benutzer authentifiziert werden müssen. Endpunkte wie Controller, Razor Pages usw., die eigene Autorisierungsanforderungen angeben, verwenden die Autorisierungsrichtlinie für Fallbacks nicht. Beispielsweise verwenden Razor Pages, Controller oder Aktionsmethoden mit [AllowAnonymous] oder [Authorize(PolicyName="MyPolicy")] das angewendete Autorisierungsattribut anstelle der Autorisierungsrichtlinie für Fallbacks.

RequireAuthenticatedUser fügt der aktuellen Instanz DenyAnonymousAuthorizationRequirement hinzu. Dadurch wird die Authentifizierung des aktuellen Benutzers erzwungen.

Statische Ressourcen unter wwwroot sind öffentlich zugänglich, weil die Middleware für statische Dateien (app.UseStaticFiles();) vor UseAuthentication aufgerufen wird. Statische Ressourcen im MyStaticFiles-Ordner erfordern eine Authentifizierung. Dies wird im Beispielcode veranschaulicht.

Eine Alternative zum Bereitstellen von Dateien basierend auf Autorisierung ist folgendes Verfahren:

  • Speichern Sie sie außerhalb von wwwroot sowie außerhalb sämtlicher Verzeichnisse, auf die die Middleware für statische Dateien zugreifen kann.
  • Stellen Sie sie über eine Aktionsmethode bereit, für die die Autorisierung gilt, und geben Sie ein FileResult-Objekt zurück:
[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");
    }
}

Verzeichnissuche

Die Verzeichnissuche ermöglicht die Verzeichnisauflistung in angegebenen Verzeichnissen.

Die Verzeichnissuche ist aus Sicherheitsgründen standardmäßig deaktiviert. Weitere Informationen finden Sie unter Sicherheitsüberlegungen für statische Dateien.

Aktivieren Sie die Verzeichnissuche mit AddDirectoryBrowser und 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();

Der vorangehende Code ermöglicht die Verzeichnissuche im Ordner wwwroot/images über die URL https://<hostname>/MyImages mit Links zu den einzelnen Dateien und Ordnern:

Verzeichnissuche

AddDirectoryBrowser fügt Dienste hinzu, die von der Middleware für die Verzeichnissuche benötigt werden, einschließlich HtmlEncoder. Diese Dienste können auch mit anderen Aufrufen hinzugefügt werden, z. B. AddRazorPages, aber wir empfehlen den Aufruf von AddDirectoryBrowser, um sicherzustellen, dass die Dienste in allen Apps hinzugefügt werden.

Bereitstellen von Standarddokumenten

Durch das Festlegen einer Standardseite wird Besuchern ein Ausgangspunkt auf einer Website bereitgestellt. Rufen Sie die UseDefaultFiles-Methode auf, um eine Standarddatei aus wwwroot zu stellen, ohne dass die Anforderungs-URL im Dateinamen enthalten sein muss:

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 muss vor UseStaticFiles aufgerufen werden, damit die Standarddatei bereitgestellt wird. UseDefaultFiles ist ein URL-Rewriter, der die Datei nicht verarbeiten kann.

Bei UseDefaultFiles werden bei Anforderungen an einen Ordner in wwwroot folgende Dateien durchsucht:

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

Die erste in der Liste gefundene Datei wird bereitgestellt, als wäre die Anforderung im Dateinamen enthalten. Die Browser-URL spiegelt weiterhin den angeforderten URI wider.

Mit dem folgenden Code wird der Standarddateiname in mydefault.html geändert:

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 für Standarddokumente

In UseFileServer werden die Funktionen von UseStaticFiles, UseDefaultFiles und (optional) UseDirectoryBrowser miteinander kombiniert.

Rufen Sie app.UseFileServer auf, um die Bereitstellung statischer Dateien und der Standarddatei zu aktivieren. Die Verzeichnissuche ist nicht aktiviert:

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

Mit dem folgenden Code wird die Bereitstellung statischer Dateien, der Standarddatei und der Verzeichnissuche aktiviert:

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

Betrachten Sie die folgende Verzeichnishierarchie:

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

Mit dem folgenden Code wird die Bereitstellung statischer Dateien, der Standarddatei und der Verzeichnissuche von MyStaticFiles aktiviert:

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 muss aufgerufen werden, wenn der EnableDirectoryBrowsing-Eigenschaftswert true lautet.

Unter Verwendung der vorstehenden Dateihierarchie und des vorangehenden Codes werden URLs wie folgt aufgelöst:

URI Antwort
https://<hostname>/StaticFiles/images/MyImage.jpg MyStaticFiles/images/MyImage.jpg
https://<hostname>/StaticFiles MyStaticFiles/default.html

Wenn im Verzeichnis MyStaticFiles keine Datei mit Standardnamen vorhanden ist, gibt https://<hostname>/StaticFiles die Verzeichnisliste mit klickbaren Links zurück:

Liste der statischen Dateien

UseDefaultFiles und UseDirectoryBrowser führen eine clientseitige Umleitung vom Ziel-URI ohne nachgestellten / zum Ziel-URI mit nachgestelltem / durch. Beispielsweise von https://<hostname>/StaticFiles zu https://<hostname>/StaticFiles/. Relative URLs im Verzeichnis StaticFiles gelten ohne nachstehenden Schrägstrich (/) als ungültig, sofern nicht die RedirectToAppendTrailingSlash-Option von DefaultFilesOptions verwendet wird.

FileExtensionContentTypeProvider

Die Klasse FileExtensionContentTypeProvider enthält eine Mappings-Eigenschaft, die als Zuordnung von Dateierweiterungen zu MIME-Inhaltstypen dient. Im folgenden Beispiel werden mehrere Dateierweiterungen bekannten MIME-Typen zugeordnet. Die Erweiterung .rtf wird ersetzt, und .mp4 wird entfernt:

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

Weitere Informationen finden Sie unter MIME-Inhaltstypen.

Inhaltstypen, die vom Standard abweichen

Die Middleware für statische Dateien erkennt fast 400 bekannte Dateiinhaltstypen. Wenn ein Benutzer eine Datei mit einem unbekannten Dateityp anfordert, übergibt die Middleware für statische Dateien die Anforderung an die nächste Middleware in der Pipeline. Wenn keine Middleware die Anforderung verarbeitet, wird die Meldung 404 Nicht gefunden zurückgegeben. Wenn die Verzeichnissuche aktiviert ist, wird ein Link zur Datei in einer Verzeichnisliste angezeigt.

Mit dem folgenden Code wird die Bereitstellung unbekannter Typen aktiviert und die unbekannte Datei als Image gerendert:

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

Mit dem vorangehenden Code wird eine Anforderung für eine Datei mit unbekanntem Inhaltstyp als Image zurückgegeben.

Warnung

Die Aktivierung von ServeUnknownFileTypes stellt ein Sicherheitsrisiko dar. Diese Eigenschaft ist standardmäßig deaktiviert, von einer Verwendung wird abgeraten. FileExtensionContentTypeProvider bietet eine sicherere Alternative für die Bereitstellung von Dateien mit vom Standard abweichenden Erweiterungen.

Bereitstellen von Dateien aus mehreren Speicherorten

Beachten Sie die folgende Razor Seite, welche die /MyStaticFiles/image3.png Datei anzeigt:

@page

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

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

Bei UseStaticFiles und UseFileServer zeigt der Dateianbieter standardmäßig auf wwwroot. Weitere Instanzen von UseStaticFiles und UseFileServer können mit anderen Dateianbietern bereitgestellt werden, um Dateien von anderen Speicherorten bereitzustellen. Das folgende Beispiel ruft UseStaticFiles zweimal auf, um Dateien aus wwwroot und MyStaticFiles zu verarbeiten:

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

Unter Verwendung des vorherigen Codes:

  • Die /MyStaticFiles/image3.png Datei wird angezeigt.
  • Die Bildtag-Hilfsprogramme AppendVersion werden nicht angewendet, da die Tag-Hilfsprogramme abhängig von WebRootFileProvider sind. WebRootFileProvider wurde nicht aktualisiert, den MyStaticFiles Ordner zu beinhalten.

Der folgende Code aktualisiert WebRootFileProvider, wodurch das Bildtag-Hilfsprogramm eine Version bereitstellen kann:

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

Sicherheitsüberlegungen für statische Dateien

Warnung

UseDirectoryBrowser und UseStaticFiles können Geheimnisse aufdecken. Eine Deaktivierung der Verzeichnissuche in der Produktionsumgebung wird dringend empfohlen. Überprüfen Sie sorgfältig, welche Verzeichnisse über UseStaticFiles oder UseDirectoryBrowser aktiviert wurden. Das gesamte Verzeichnis und die zugehörigen Unterverzeichnisse werden öffentlich zugänglich gemacht. Speichern Sie Dateien, die für eine Bereitstellung in der Öffentlichkeit geeignet sind, in einem dafür vorgesehenen Verzeichnis wie z.B. <content_root>/wwwroot. Trennen Sie diese Dateien von MVC-Ansichten, Razor Pages, Konfigurationsdateien usw.

  • Die URLs für Inhalte, die mit UseDirectoryBrowser und UseStaticFiles verfügbar gemacht wurden, unterliegen der Groß-/Kleinschreibung und den Zeichenbeschränkungen des zugrunde liegenden Dateisystems. Bei Windows wird die Groß-/Kleinschreibung beispielsweise nicht beachtet, jedoch bei macOS und Linux.

  • In IIS gehostete ASP.NET Core-Apps leiten über das ASP.NET Core-Modul alle Anforderungen an die App weiter, darunter die Anforderungen von statischen Dateien. Der IIS-Handler für statische Dateien wird nicht verwendet und hat keine Möglichkeit, Anforderungen zu verarbeiten.

  • Führen Sie im IIS-Manager die folgenden Schritte aus, um den statischen IIS-Dateihandler auf Server- oder Website-Ebene zu entfernen:

    1. Navigieren Sie zum Feature Module.
    2. Wählen Sie StaticFileModule aus der Liste aus.
    3. Klicken Sie in der Randleiste Aktionen auf Entfernen.

Warnung

Wenn der statische IIS-Dateihandler aktiviert ist und das ASP.NET Core-Modul falsch konfiguriert wurde, werden statische Dateien bereitgestellt. Dies geschieht beispielsweise, wenn die Datei web.config nicht bereitgestellt worden ist.

  • Platzieren Sie Codedateien einschließlich .cs und .cshtml außerhalb des Webstammverzeichnisses des App-Projekts. Aus diesem Grund wird eine logische Trennung zwischen den clientseitigen Inhalten der App und dem serverbasierten Code erschaffen. Dadurch wird verhindert, dass serverseitiger Code aufgedeckt wird.

Bedienen Sie Dateien außerhalb von wwwroot, indem Sie IWebHostEnvironment.WebRootPath aktualisieren

Wenn IWebHostEnvironment.WebRootPath auf einen anderen Ordner als wwwroot festgelegt ist:

  • In der Entwicklungsumgebung werden statische Ressourcen, die sich sowohl unter wwwroot als auch dem aktualisierten IWebHostEnvironment.WebRootPath befinden, von wwwroot bedient.
  • In jeder anderen Umgebung als der Entwicklungsumgebung werden doppelt vorhandene statische Ressourcen aus dem aktualisierten IWebHostEnvironment.WebRootPath-Ordner bereitgestellt.

Betrachten Sie eine Web-App, die mit der leeren Webvorlage erstellt wurde:

  • Sie enthält eine Datei Index.html in wwwroot und wwwroot-custom.

  • Mit der folgenden aktualisierten Program.cs-Datei, die WebRootPath = "wwwroot-custom" festlegt:

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

Im vorhergehenden Code bewirken Anforderungen an / Folgendes:

  • In der Entwicklungsumgebung wird wwwroot/Index.html zurückgegeben
  • In jeder anderen Umgebung als der Entwicklungsumgebung wird wwwroot-custom/Index.html zurückgegeben

Verwenden Sie eine der folgenden Ansätze, um sicherzustellen, dass Ressourcen aus wwwroot-custom zurückgegeben werden:

  • Löschen Sie doppelte benannte Ressourcen in wwwroot.

  • Legen Sie "ASPNETCORE_ENVIRONMENT" in Properties/launchSettings.json auf einen beliebigen anderen Wert als "Development" fest.

  • Deaktivieren Sie statische Webressourcen vollständig, indem Sie <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled> in der Projektdatei festlegen. WARNUNG: Durch das Deaktivieren statischer Webressourcen werden die Razor-Klassenbibliotheken deaktiviert.

  • Fügen Sie der Projektdatei den folgenden JSON-Code hinzu:

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

Der folgende Code aktualisiert IWebHostEnvironment.WebRootPath auf einen nicht auf die Entwicklung bezogenen Wert, der garantiert, dass doppelte Inhalte aus wwwroot-custom anstelle von wwwroot zurückgegeben werden:

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

Zusätzliche Ressourcen

Von Rick Anderson und Kirk Larkin

Bei statischen Dateien wie HTML, CSS, Images und JavaScript handelt es sich um Objekte, die Clients von einer ASP.NET Core-App standardmäßig direkt bereitgestellt werden.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Bereitstellen statischer Dateien

Statische Dateien werden im Webstammverzeichnis des Projekts gespeichert. Das Standardverzeichnis lautet {content root}/wwwroot, kann jedoch mit der Methode UseWebRoot geändert werden. Weitere Informationen finden Sie unter Inhaltsstammverzeichnis und Webstammverzeichnis.

Die Methode CreateDefaultBuilder legt das Inhaltsstammverzeichnis auf das aktuelle Verzeichnis fest:

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

Der vorangehende Code wurde mit der Web-App-Vorlage erstellt.

Auf statische Dateien kann über einen Pfad relativ zum Webstammverzeichnis zugegriffen werden. Die Webanwendung-Projektvorlagen verfügen beispielsweise über mehrere Ordner innerhalb des Ordners wwwroot:

  • wwwroot
    • css
    • js
    • lib

Erstellen Sie ggf. den wwwroot/images-Ordner, und fügen Sie die Datei wwwroot/images/MyImage.jpg hinzu. Das URI-Format für den Zugriff auf eine Datei im images-Ordner ist https://<hostname>/images/<image_file_name>. Beispiel: https://localhost:5001/images/MyImage.jpg

Verarbeiten von Dateien im Webstammverzeichnis

Mit den Standard-Webappvorlagen wird die UseStaticFiles-Methode in Startup.Configure aufgerufen, die die Verarbeitung statischer Dateien ermöglicht:

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

Die parameterlose Überladung der Methode UseStaticFiles markiert die Dateien im Webstammverzeichnis als bereitstellbar. Folgendes Markup verweist auf wwwroot/images/MyImage.jpg:

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

Im vorhergehenden Code verweist die Tilde (~/) auf das Webstammverzeichnis.

Bereitstellen von Dateien außerhalb des Webstammverzeichnisses

Erwägen Sie eine Verzeichnishierarchie, bei der sich die bereitzustellenden statischen Dateien außerhalb des Webstammverzeichnisses befinden:

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

Über eine Anforderung kann auf die Datei red-rose.jpg zugegriffen werden, indem die Middleware für statische Dateien wie folgt konfiguriert wird:

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

Im vorangehenden Code wird die MyStaticFiles-Verzeichnishierarchie öffentlich über das URI-Segment StaticFiles verfügbar gemacht. Eine Anforderung an https://<hostname>/StaticFiles/images/red-rose.jpg dient der red-rose.jpg-Datei.

Folgendes Markup verweist auf MyStaticFiles/images/red-rose.jpg:

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

Festlegen von HTTP-Antwortheadern

Mit einem StaticFileOptions-Objekt können HTTP-Antwortheader festgelegt werden. Neben der Konfiguration statischer, über das Webstammverzeichnis bereitgestellter Dateien wird mit dem folgenden Code der Header Cache-Control festgelegt:

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

Der vorangehende Code legt „max-age“ auf 604800 Sekunden (7 Tage) fest.

Antwortheader mit dem Cache-Control-Header wurden hinzugefügt

Autorisierung statischer Dateien

Die ASP.NET Core-Vorlagen rufen UseStaticFiles vor UseAuthorization auf. Die meisten Apps folgen diesem Muster. Wenn die Middleware für statische Dateien vor der Autorisierungsmiddleware aufgerufen wird, gilt Folgendes:

  • In den statischen Dateien werden keine Autorisierungsüberprüfungen durchgeführt.
  • Statische Dateien, die von der Middleware für statische Dateien bereitgestellt werden – wie beispielsweise diejenigen unter wwwroot – sind öffentlich zugänglich.

So stellen Sie statische Dateien basierend auf Autorisierung bereit:

  • Speichern Sie sie außerhalb von wwwroot.
  • Rufen Sie UseStaticFiles nach dem Aufruf von UseAuthorization auf, und geben Sie einen Pfad an.
  • Legen Sie die Autorisierungsrichtlinie für Fallbacks fest.
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.

Im vorstehenden Code erfordert die Richtlinie für die Fallbackautorisierung, dass alle Benutzer authentifiziert werden müssen. Endpunkte wie Controller, Razor Pages usw., die eigene Autorisierungsanforderungen angeben, verwenden die Autorisierungsrichtlinie für Fallbacks nicht. Beispielsweise verwenden Razor Pages, Controller oder Aktionsmethoden mit [AllowAnonymous] oder [Authorize(PolicyName="MyPolicy")] das angewendete Autorisierungsattribut anstelle der Autorisierungsrichtlinie für Fallbacks.

RequireAuthenticatedUser fügt der aktuellen Instanz DenyAnonymousAuthorizationRequirement hinzu. Dadurch wird die Authentifizierung des aktuellen Benutzers erzwungen.

Statische Ressourcen unter wwwroot sind öffentlich zugänglich, weil die Middleware für statische Dateien (app.UseStaticFiles();) vor UseAuthentication aufgerufen wird. Statische Ressourcen im MyStaticFiles-Ordner erfordern eine Authentifizierung. Dies wird im Beispielcode veranschaulicht.

Eine Alternative zum Bereitstellen von Dateien basierend auf Autorisierung ist folgendes Verfahren:

  • Speichern Sie sie außerhalb von wwwroot sowie außerhalb sämtlicher Verzeichnisse, auf die die Middleware für statische Dateien zugreifen kann.
  • Stellen Sie sie über eine Aktionsmethode bereit, für die die Autorisierung gilt, und geben Sie ein FileResult-Objekt zurück:
[Authorize]
public IActionResult BannerImage()
{
    var filePath = Path.Combine(
        _env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");

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

Verzeichnissuche

Die Verzeichnissuche ermöglicht die Verzeichnisauflistung in angegebenen Verzeichnissen.

Die Verzeichnissuche ist aus Sicherheitsgründen standardmäßig deaktiviert. Weitere Informationen finden Sie unter Sicherheitsüberlegungen für statische Dateien.

Aktivieren Sie die Verzeichnissuche mit:

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

Der vorangehende Code ermöglicht die Verzeichnissuche im Ordner wwwroot/images über die URL https://<hostname>/MyImages mit Links zu den einzelnen Dateien und Ordnern:

Verzeichnissuche

Bereitstellen von Standarddokumenten

Durch das Festlegen einer Standardseite wird Besuchern ein Ausgangspunkt auf einer Website bereitgestellt. Rufen Sie die UseDefaultFiles-Methode auf, um eine Standarddatei aus wwwroot zu stellen, ohne dass die Anforderungs-URL im Dateinamen enthalten sein muss:

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 muss vor UseStaticFiles aufgerufen werden, damit die Standarddatei bereitgestellt wird. UseDefaultFiles ist ein URL-Rewriter, der die Datei nicht verarbeiten kann.

Bei UseDefaultFiles werden bei Anforderungen an einen Ordner in wwwroot folgende Dateien durchsucht:

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

Die erste in der Liste gefundene Datei wird bereitgestellt, als wäre die Anforderung im Dateinamen enthalten. Die Browser-URL spiegelt weiterhin den angeforderten URI wider.

Mit dem folgenden Code wird der Standarddateiname in mydefault.html geändert:

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

Der folgende Code zeigt Startup.Configure mit dem vorherigen Code:

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 für Standarddokumente

In UseFileServer werden die Funktionen von UseStaticFiles, UseDefaultFiles und (optional) UseDirectoryBrowser miteinander kombiniert.

Rufen Sie app.UseFileServer auf, um die Bereitstellung statischer Dateien und der Standarddatei zu aktivieren. Die Verzeichnissuche ist nicht aktiviert. Der folgende Code zeigt Startup.Configure mit UseFileServer an:

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

Mit dem folgenden Code wird die Bereitstellung statischer Dateien, der Standarddatei und der Verzeichnissuche aktiviert:

app.UseFileServer(enableDirectoryBrowsing: true);

Der folgende Code zeigt Startup.Configure mit dem vorherigen Code:

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

Betrachten Sie die folgende Verzeichnishierarchie:

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

Mit dem folgenden Code wird die Bereitstellung statischer Dateien, der Standarddatei und der Verzeichnissuche von MyStaticFiles aktiviert:

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 muss aufgerufen werden, wenn der EnableDirectoryBrowsing-Eigenschaftswert true lautet.

Unter Verwendung der Dateihierarchie und des vorangehenden Codes werden URLs wie folgt aufgelöst:

URI Antwort
https://<hostname>/StaticFiles/images/MyImage.jpg MyStaticFiles/images/MyImage.jpg
https://<hostname>/StaticFiles MyStaticFiles/default.html

Wenn im Verzeichnis MyStaticFiles keine Datei mit Standardnamen vorhanden ist, gibt https://<hostname>/StaticFiles die Verzeichnisliste mit klickbaren Links zurück:

Liste der statischen Dateien

UseDefaultFiles und UseDirectoryBrowser führen eine clientseitige Umleitung vom Ziel-URI ohne nachgestellten / zum Ziel-URI mit nachgestelltem / durch. Beispielsweise von https://<hostname>/StaticFiles zu https://<hostname>/StaticFiles/. Relative URLs im Verzeichnis StaticFiles gelten ohne nachstehenden Schrägstrich (/) als ungültig.

FileExtensionContentTypeProvider

Die Klasse FileExtensionContentTypeProvider enthält eine Mappings-Eigenschaft, die als Zuordnung von Dateierweiterungen zu MIME-Inhaltstypen dient. Im folgenden Beispiel werden mehrere Dateierweiterungen bekannten MIME-Typen zugeordnet. Die Erweiterung .rtf wird ersetzt, und .mp4 wird entfernt:

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

Der folgende Code zeigt Startup.Configure mit dem vorherigen Code:

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

Weitere Informationen finden Sie unter MIME-Inhaltstypen.

Inhaltstypen, die vom Standard abweichen

Die Middleware für statische Dateien erkennt fast 400 bekannte Dateiinhaltstypen. Wenn ein Benutzer eine Datei mit einem unbekannten Dateityp anfordert, übergibt die Middleware für statische Dateien die Anforderung an die nächste Middleware in der Pipeline. Wenn keine Middleware die Anforderung verarbeitet, wird die Meldung 404 Nicht gefunden zurückgegeben. Wenn die Verzeichnissuche aktiviert ist, wird ein Link zur Datei in einer Verzeichnisliste angezeigt.

Mit dem folgenden Code wird die Bereitstellung unbekannter Typen aktiviert und die unbekannte Datei als Image gerendert:

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

Der folgende Code zeigt Startup.Configure mit dem vorherigen Code:

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

Mit dem vorangehenden Code wird eine Anforderung für eine Datei mit unbekanntem Inhaltstyp als Image zurückgegeben.

Warnung

Die Aktivierung von ServeUnknownFileTypes stellt ein Sicherheitsrisiko dar. Diese Eigenschaft ist standardmäßig deaktiviert, von einer Verwendung wird abgeraten. FileExtensionContentTypeProvider bietet eine sicherere Alternative für die Bereitstellung von Dateien mit vom Standard abweichenden Erweiterungen.

Bereitstellen von Dateien aus mehreren Speicherorten

Bei UseStaticFiles und UseFileServer zeigt der Dateianbieter standardmäßig auf wwwroot. Weitere Instanzen von UseStaticFiles und UseFileServer können mit anderen Dateianbietern bereitgestellt werden, um Dateien von anderen Speicherorten bereitzustellen. Weitere Informationen finden Sie in diesem GitHub-Issue.

Sicherheitsüberlegungen für statische Dateien

Warnung

UseDirectoryBrowser und UseStaticFiles können Geheimnisse aufdecken. Eine Deaktivierung der Verzeichnissuche in der Produktionsumgebung wird dringend empfohlen. Überprüfen Sie sorgfältig, welche Verzeichnisse über UseStaticFiles oder UseDirectoryBrowser aktiviert wurden. Das gesamte Verzeichnis und die zugehörigen Unterverzeichnisse werden öffentlich zugänglich gemacht. Speichern Sie Dateien, die für eine Bereitstellung in der Öffentlichkeit geeignet sind, in einem dafür vorgesehenen Verzeichnis wie z.B. <content_root>/wwwroot. Trennen Sie diese Dateien von MVC-Ansichten, Razor Pages, Konfigurationsdateien usw.

  • Die URLs für Inhalte, die mit UseDirectoryBrowser und UseStaticFiles verfügbar gemacht wurden, unterliegen der Groß-/Kleinschreibung und den Zeichenbeschränkungen des zugrunde liegenden Dateisystems. Bei Windows wird die Groß-/Kleinschreibung beispielsweise nicht beachtet, jedoch bei macOS und Linux.

  • In IIS gehostete ASP.NET Core-Apps leiten über das ASP.NET Core-Modul alle Anforderungen an die App weiter, darunter die Anforderungen von statischen Dateien. Der IIS-Handler für statische Dateien wird nicht verwendet und hat keine Möglichkeit, Anforderungen zu verarbeiten.

  • Führen Sie im IIS-Manager die folgenden Schritte aus, um den statischen IIS-Dateihandler auf Server- oder Website-Ebene zu entfernen:

    1. Navigieren Sie zum Feature Module.
    2. Wählen Sie StaticFileModule aus der Liste aus.
    3. Klicken Sie in der Randleiste Aktionen auf Entfernen.

Warnung

Wenn der statische IIS-Dateihandler aktiviert ist und das ASP.NET Core-Modul falsch konfiguriert wurde, werden statische Dateien bereitgestellt. Dies geschieht beispielsweise, wenn die Datei web.config nicht bereitgestellt worden ist.

  • Platzieren Sie Codedateien einschließlich .cs und .cshtml außerhalb des Webstammverzeichnisses des App-Projekts. Aus diesem Grund wird eine logische Trennung zwischen den clientseitigen Inhalten der App und dem serverbasierten Code erschaffen. Dadurch wird verhindert, dass serverseitiger Code aufgedeckt wird.

Zusätzliche Ressourcen