Partager via


Fichiers statiques dans ASP.NET Core

Note

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 10 de cet article.

Warning

Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la stratégie de support .NET et .NET Core. Pour la version actuelle, consultez la version .NET 10 de cet article.

Les fichiers statiques, également appelés ressources statiques, sont des fichiers d’une application ASP.NET Core qui ne sont pas générées dynamiquement. Au lieu de cela, ils sont directement servis aux clients à la demande, tels que les fichiers HTML, CSS, image et JavaScript.

Pour obtenir des conseils sur les fichiers statiques Blazor, qui s'ajoutent aux recommandations de cet article ou les remplacent, consultez fichiers statiques Blazor ASP.NET Core.

Pour activer la gestion statique des fichiers dans ASP.NET Core, appelez MapStaticAssets.

Par défaut, les fichiers statiques sont stockés dans le répertoire racine web du projet. Le répertoire par défaut est {CONTENT ROOT}/wwwroot, où l’espace {CONTENT ROOT} réservé est la racine de contenu de l’application. Seuls les fichiers du dossier wwwroot sont adressables. Vous n’avez donc pas besoin de vous soucier du reste de votre code.

Seuls les fichiers avec des extensions de fichier spécifiques mappées aux types multimédias pris en charge sont traités comme des ressources web statiques.

Les ressources web statiques sont découvertes au moment de la génération et optimisées à l’aide d’empreintes digitales basées sur le contenu pour empêcher la réutilisation des anciens fichiers. Les ressources sont également compressées pour réduire le temps de livraison des ressources.

Au moment de l'exécution, les ressources web statiques découvertes sont exposées en tant que points de terminaison avec des en-têtes HTTP appliqués, tels que les en-têtes de mise en cache et les en-têtes de type de contenu. Une ressource est servie une fois jusqu’à ce que le fichier change ou que le navigateur efface son cache. Les en-têtes ETag, Last-Modified et Content-Type sont définis. Le navigateur est empêché d’utiliser des ressources obsolètes après la mise à jour d’une application.

La remise des ressources statiques est basée sur le routage des points de terminaison. Elle fonctionne donc avec d’autres fonctionnalités prenant en charge les points de terminaison, telles que l’autorisation. Il est conçu pour fonctionner avec toutes les infrastructures d’interface utilisateur, notamment Blazor, Razor Pages et MVC.

Les ressources statiques mappées offrent les avantages suivants :

  • Compression au moment de la génération pour toutes les ressources de l’application, y compris JavaScript (JS) et les feuilles de style, mais à l’exclusion des ressources d’image et de police déjà compressées. La compression Gzip (Content-Encoding: gz) est utilisée pendant le développement. La compression Gzip et Brotli (Content-Encoding: br) sont utilisées pendant la publication.
  • La collecte d’empreintes digitales pour toutes les ressources lors de la génération avec une chaîne codée en Base64 du hachage SHA-256 du contenu de chaque fichier. Cela empêche la réutilisation d’une ancienne version d’un fichier, même si l’ancien fichier est mis en cache. Les ressources d’empreintes digitales sont mises en cache à l’aide de la directive immutable, ce qui fait que le navigateur ne demande plus jamais la ressource tant qu’elle n’a pas changé. Pour les navigateurs qui ne prennent pas en charge la directive immutable, une directive max-age est ajoutée.
    • Même si une ressource n’est pas sous forme d’empreinte, des ETags basés sur le contenu sont créés pour chaque ressource statique en utilisant le hachage de l’empreinte du fichier comme valeur ETag. Cela garantit que le navigateur télécharge uniquement un fichier si son contenu change (ou si le fichier est téléchargé pour la première fois).
    • En interne, l’infrastructure mappe les ressources physiques à leurs empreintes digitales, ce qui permet à l’application de :
      • Recherchez des ressources générées automatiquement, telles que le CSS délimité par le composant Razor pour la fonction d’isolation CSS de Blazor et les ressources JS décrites par les mappages d’importation JS.
      • Générez des balises de lien dans le contenu <head> de la page pour précharger les ressources.

Mapper les ressources statiques ne fournit pas de fonctionnalités pour la minification ou d’autres transformations de fichiers. La minimisation est généralement gérée par du code personnalisé ou des outils tiers.

Pour activer la gestion statique des fichiers dans ASP.NET Core, appelez UseStaticFiles.

Par défaut, les fichiers statiques sont stockés dans le répertoire racine web du projet. Le répertoire par défaut est {CONTENT ROOT}/wwwroot, où l’espace {CONTENT ROOT} réservé est la racine de contenu de l’application. Seuls les fichiers du dossier wwwroot sont adressables. Vous n’avez donc pas besoin de vous soucier du reste de votre code.

Au moment de l’exécution, les ressources web statiques sont retournées par l’intergiciel de fichier statique lorsqu’elles sont demandées avec la modification des ressources et les en-têtes de type de contenu appliqués. Les en-têtes ETag, Last-Modified et Content-Type sont définis.

L’intergiciel de fichiers statiques active le service de fichiers statiques et est utilisé par une application lorsqu’elle UseStaticFiles est appelée dans le pipeline de traitement des demandes de l’application. Les fichiers sont servis à partir du chemin d’accès spécifié dans IWebHostEnvironment.WebRootPath ou WebRootFileProvider, qui correspond par défaut au dossier racine web, généralement wwwroot.

Vous pouvez également servir des ressources web statiques à partir de projets et de packages référencés.

Modifier le répertoire racine web

Utilisez la UseWebRoot méthode si vous souhaitez modifier la racine web. Pour plus d’informations, consultez ASP.NET vue d’ensemble des principes fondamentaux de base.

Empêchez la publication de fichiers dans wwwroot avec l’élément de projet <Content> dans le fichier de projet. L’exemple suivant empêche la publication de contenu dans wwwroot/local et de ses sous-répertoires :

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

La méthode CreateBuilder définit le répertoire actif comme racine du contenu :

var builder = WebApplication.CreateBuilder(args);

La méthode CreateDefaultBuilder définit le répertoire actif comme racine du contenu :

Host.CreateDefaultBuilder(args)

Dans le pipeline de traitement des demandes après l’appel à UseHttpsRedirection, appelez MapStaticAssets dans le pipeline de traitement des demandes de l’application pour permettre de servir les fichiers statiques depuis la racine web de l’application :

app.MapStaticAssets();

Dans le pipeline de traitement des demandes après l’appel à UseHttpsRedirection, appelez UseStaticFiles dans le pipeline de traitement des demandes de l’application pour permettre de servir les fichiers statiques depuis la racine web de l’application :

app.UseStaticFiles();

Les fichiers statiques sont accessibles via un chemin relatif à la racine web.

Pour accéder à une image à l’adresse wwwroot/images/favicon.pngsuivante :

  • Format d’URL : https://{HOST}/images/{FILE NAME}
    • L’hôte est l’espace réservé {HOST}.
    • Le {FILE NAME} espace réservé est le nom du fichier.
  • Exemples
    • URL absolue : https://localhost:5001/images/favicon.png
    • URL relative à la racine : images/favicon.png

Dans une Blazor application, images/favicon.png charge l’image d’icône (favicon.png) à partir du dossier de l’application wwwroot/images :

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

Dans les Razor applications Pages et MVC, le caractère ~ tilde pointe vers la racine du site. Dans l’exemple suivant, ~/images/favicon.png charge l’image d’icône (favicon.png) à partir du dossier de l’application wwwroot/images :

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

Court-circuiter le pipeline d’intergiciel

Pour éviter d’exécuter l’intégralité du pipeline d’intergiciels après la mise en correspondance d’une ressource statique, qui est le comportement de UseStaticFiles, appelez ShortCircuit sur MapStaticAssets. L’appel ShortCircuit exécute immédiatement le point de terminaison et retourne la réponse, empêchant l’exécution d’autres intergiciels pour les demandes de ressources statiques :

app.MapStaticAssets().ShortCircuit();

Contrôler la mise en cache des fichiers statiques pendant le développement

Lors de l’exécution dans l’environnement Development, par exemple pendant les tests de rechargement à chaud au cours du développement avec Visual Studio, le framework remplace les en-têtes de cache pour empêcher les navigateurs de mettre en cache des fichiers statiques. Cela permet de s’assurer que la dernière version des fichiers est utilisée lors de la modification des fichiers, ce qui évite les problèmes liés au contenu obsolète. En production, les en-têtes de cache corrects sont définis, ce qui permet aux navigateurs de mettre en cache les ressources statiques comme prévu.

Pour désactiver ce comportement, définissez EnableStaticAssetsDevelopmentCaching à true dans le fichier de paramètres de l'application de l'environnement Development (appsettings.Development.json).

Fichiers statiques dans des environnements non-Development

Lors de l’exécution locale d’une application, les ressources web statiques sont uniquement activées dans l’environnement Development . Pour activer les fichiers statiques pour des environnements autres que Development pendant le développement et les tests locaux (par exemple, dans l’environnement Staging), appelez UseStaticWebAssets sur le WebApplicationBuilder.

Warning

Appelez UseStaticWebAssetsl’environnement exact pour empêcher l’activation de la fonctionnalité en production, car elle sert des fichiers à partir d’emplacements distincts sur le disque autre que celui du projet. L’exemple de cette section vérifie l’environnement Staging avec IsStaging.

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

Servir des fichiers en dehors du répertoire racine web via IWebHostEnvironment.WebRootPath

Quand IWebHostEnvironment.WebRootPath est défini sur un dossier autre que wwwroot, les comportements par défaut suivants sont exposés :

  • Dans l’environnement Development , les ressources statiques sont traitées à partir de wwwroot si les ressources portant le même nom se trouvent dans les deux wwwroot et dans un autre dossier affecté à WebRootPath.
  • Dans n’importe quel environnement autre que Development, les ressources statiques en double sont servies à partir du WebRootPath dossier.

Considérez une application web créée à partir du modèle web vide :

  • Contenant un fichier Index.html dans wwwroot et wwwroot-custom.
  • Le Program fichier est mis à jour pour définir WebRootPath = "wwwroot-custom".
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    Args = args,
    WebRootPath = "wwwroot-custom"
});

Par défaut, pour les demandes à /:

  • Dans l’environnement Development , wwwroot/Index.html est retourné.
  • Dans n’importe quel environnement autre que Development, wwwroot-custom/Index.html est retourné.

Pour vous assurer que les actifs provenant de wwwroot-custom sont toujours retournés, utilisez l’une des approches suivantes :

  • Supprimer les ressources portant des noms en double dans wwwroot.

  • Définissez ASPNETCORE_ENVIRONMENT dans Properties/launchSettings.json sur n’importe quelle valeur autre que Development.

  • Désactivez les ressources web statiques en définissant <StaticWebAssetsEnabled> sur false dans le fichier projet de l'application. AVERTISSEMENT: La désactivation des ressources web statiques désactive les bibliothèquesRazor de classes.

  • Ajoutez le code XML suivant au fichier projet :

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

Le code suivant met à jour WebRootPath à une valeur autre que Développement (Staging), ce qui garantit que le contenu en double est retourné de wwwroot-custom plutôt que de wwwroot :

var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    Args = args,
    EnvironmentName = Environments.Staging,
    WebRootPath = "wwwroot-custom"
});

Intergiciel de fichiers statiques

L’intergiciel Static File permet de servir des fichiers statiques dans des scénarios spécifiques, généralement en complément des conventions de routage de point de terminaison de Map Static Assets (MapStaticAssets).

L’intergiciel de fichiers statiques est inclus dans le traitement des demandes lorsqu’il UseStaticFiles est appelé dans le pipeline de traitement des demandes de l’application, généralement après l’ajout des conventions de point de terminaison Map Static Assets (MapStaticAssets).

Les conventions de point de terminaison des ressources statiques mappées sont utilisées dans les applications qui ciblent .NET 9 ou version ultérieure. L’intergiciel de fichier statique doit être utilisé dans les applications qui ciblent les versions de .NET antérieures à .NET 9.

L’intergiciel de fichiers statiques sert des fichiers statiques, mais il ne fournit pas le même niveau d’optimisation que les conventions de point de terminaison Map Static Assets. Les fonctionnalités de compression et d’empreinte digitale au moment de la génération des conventions de point de terminaison Map Static Assets ne sont pas disponibles quand elles s’appuient uniquement sur l’intergiciel de fichiers statiques.

Les conventions de point de terminaison sont optimisées pour servir les ressources dont l’application a connaissance au moment de l’exécution. Si l’application sert des ressources à partir d’autres emplacements, tels que des ressources disque ou incorporées, l’intergiciel de fichiers statiques doit être utilisé.

Les fonctionnalités suivantes décrites dans cet article sont prises en charge avec l'intergiciel de fichiers statiques, mais pas avec les conventions de point de terminaison pour mapper les ressources statiques :

Servir des fichiers en dehors du répertoire racine web via UseStaticFiles

Considérez la hiérarchie de répertoires suivante avec des fichiers statiques résidant en dehors de la racine web de l’application dans un dossier nommé ExtraStaticFiles:

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

Une demande peut accéder red-rose.jpg en configurant une nouvelle instance de middleware de fichiers statiques :

Espaces de noms pour les API suivantes :

using Microsoft.Extensions.FileProviders;

Dans le pipeline de traitement des demandes après l’appel existant à MapStaticAssets (.NET 9 ou version ultérieure) ou UseStaticFiles (.NET 8 ou version antérieure) :

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

Dans le code précédent, la ExtraStaticFiles hiérarchie de répertoires est exposée publiquement via le segment d’URL static-files . Une requête est envoyée à https://{HOST}/StaticFiles/images/red-rose.jpg, où l'espace réservé {HOST} est l'hôte, pour servir le fichier red-rose.jpg.

Ce qui suit fait référence à ExtraStaticFiles/images/red-rose.jpg :

<img src="static-files/images/red-rose.jpg" alt="A red rose" />

Pour l’exemple précédent, la notation de barre oblique tilde est prise en charge dans Razor Pages et vues MVC (src="~/StaticFiles/images/red-rose.jpg"), mais pas pour les Razor composants dans les applications Blazor.

Délivrer des fichiers à partir de plusieurs emplacements

Les conseils de cette section s’appliquent aux applications de Razor Pages et MVC. Pour des conseils qui s'appliquent aux Blazor Web Apps, voir ASP.NET Core Blazorfichiers statiques.

Considérez le balisage suivant qui affiche un logo d’entreprise :

<img src="~/logo.png" asp-append-version="true" alt="Company logo">

Le développeur a l’intention d’utiliser le Tag Helper image pour ajouter une version et servir le fichier à partir d’un emplacement personnalisé, un dossier nommé ExtraStaticFiles.

L’exemple suivant appelle MapStaticAssets pour servir des fichiers à partir de wwwroot et UseStaticFiles pour servir des fichiers à partir de ExtraStaticFiles.

Dans le pipeline de traitement des demandes après l’appel existant à MapStaticAssets (.NET 9 ou version ultérieure) ou UseStaticFiles (.NET 8 ou version antérieure) :

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

L’exemple suivant appelle UseStaticFiles deux fois pour traiter des fichiers à partir des deux wwwroot et ExtraStaticFiles.

Dans le pipeline de traitement des demandes après l’appel existant à UseStaticFiles:

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

À l’aide du code précédent, le ExtraStaticFiles/logo.png fichier s’affiche. Toutefois, le Tag Helper d’image (AppendVersion) n’est pas appliqué, car le Tag Helper dépend de WebRootFileProvider, qui n’a pas été mis à jour pour inclure le dossier ExtraStaticFiles.

Le code suivant met à jour le dossier WebRootFileProvider pour inclure le dossier ExtraStaticFiles à l’aide d’un CompositeFileProvider. Cela permet au Tag Helper d’image d’appliquer une version aux images dans le ExtraStaticFiles dossier.

Espace de noms pour l’interface de programmation (API) suivante :

using Microsoft.Extensions.FileProviders;

Dans le pipeline de traitement des demandes avant l’appel existant à MapStaticAssets (.NET 9 ou version ultérieure) ou UseStaticFiles (.NET 8 ou version antérieure) :

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

var compositeProvider = new CompositeFileProvider(webRootProvider, newPathProvider);

app.Environment.WebRootFileProvider = compositeProvider;

UseStaticFiles et UseFileServer correspondent par défaut au fournisseur de fichiers pointant sur wwwroot. Des instances supplémentaires de UseStaticFiles et UseFileServer peuvent être fournies avec d’autres fournisseurs de fichiers pour délivrer des fichiers à partir d’autres emplacements. Pour plus d’informations, consultez UseStaticFiles toujours nécessaire avec UseFileServer pour wwwroot (dotnet/AspNetCore.Docs #15578).

Définir des en-têtes de réponse HTTP

Permet StaticFileOptions de définir des en-têtes de réponse HTTP. Outre la configuration du middleware de fichiers statiques pour traiter les fichiers statiques, le code suivant définit l’en-têteCache-Control sur 604 800 secondes (une semaine).

Espaces de noms pour les API suivantes :

using Microsoft.AspNetCore.Http;

Dans le pipeline de traitement des demandes après l’appel existant à MapStaticAssets (.NET 9 ou version ultérieure) ou UseStaticFiles (.NET 8 ou version antérieure) :

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

Grande collection de ressources

Lorsque vous traitez de grandes collections de ressources, qui est considérée comme environ 1 000 ressources ou plus, nous vous recommandons d’utiliser un bundler pour réduire le nombre final de ressources servies par l’application ou de combiner MapStaticAssets avec UseStaticFiles.

MapStaticAssets charge avec impatience les métadonnées précomputées capturées pendant le processus de génération pour les ressources afin de prendre en charge la compression, la mise en cache et l’empreinte digitale. Ces fonctionnalités proviennent du coût d’une utilisation accrue de la mémoire par l’application. Pour les ressources fréquemment consultées, il vaut généralement la peine de payer les coûts. Pour les biens qui ne sont pas fréquemment consultés, le compromis peut ne pas valoir les coûts.

Si vous n’utilisez pas de regroupement, nous vous recommandons de combiner MapStaticAssets avec UseStaticFiles. L’exemple suivant illustre l’approche.

Dans le fichier projet (.csproj), la StaticWebAssetEndpointExclusionPattern propriété MSBuild est utilisée pour filtrer les points de terminaison à partir du manifeste final pour MapStaticAssets. Les fichiers exclus sont servis par UseStaticFiles et ne bénéficient pas de la compression, de la mise en cache et de l’empreinte numérique.

Lors de la définition de la valeur de StaticWebAssetEndpointExclusionPattern, conservez $(StaticWebAssetEndpointExclusionPattern) pour garder le modèle d’exclusion par défaut du framework. Ajoutez des modèles supplémentaires dans une liste séparée par des points-virgules.

Dans l’exemple suivant, le motif d’exclusion ajoute les fichiers statiques du dossier lib/icons, qui représente un lot hypothétique d’icônes.

<StaticWebAssetEndpointExclusionPattern>
  $(StaticWebAssetEndpointExclusionPattern);lib/icons/**
</StaticWebAssetEndpointExclusionPattern>

Après le traitement du middleware de redirection HTTPS (app.UseHttpsRedirection();) dans le fichier Program :

app.UseStaticFiles();

app.UseAuthorization();

app.MapStaticAssets();

Autorisations des fichiers statiques

Lorsqu'une application adopte une stratégie d'autorisation de secours, l'autorisation est requise pour toutes les requêtes qui ne spécifient pas explicitement de stratégie d'autorisation, y compris les requêtes pour des fichiers statiques, après que le middleware d'autorisation a traité les requêtes. Autorisez l’accès anonyme aux fichiers statiques en appliquant AllowAnonymousAttribute au générateur de points de terminaison pour les fichiers statiques :

app.MapStaticAssets().Add(endpointBuilder => 
    endpointBuilder.Metadata.Add(new AllowAnonymousAttribute()));

Lorsqu'une application adopte une stratégie d'autorisation de secours, l'autorisation est requise pour toutes les requêtes qui ne spécifient pas explicitement de stratégie d'autorisation, y compris les requêtes pour des fichiers statiques, après que le middleware d'autorisation a traité les requêtes. Les modèles ASP.NET Core autorisent l’accès anonyme aux fichiers statiques en appelant UseStaticFiles avant d’appeler UseAuthorization. La plupart des applications suivent ce modèle. Quand l’intergiciel de fichiers statiques est appelé avant l’intergiciel d’autorisation :

  • Aucune vérification d’autorisation n’est effectuée sur les fichiers statiques.
  • Les fichiers statiques servis par le Middleware de fichiers statiques, tels que ceux de la racine web (généralement, wwwroot), sont accessibles publiquement.

Pour délivrer des fichiers statiques en fonction d’une autorisation :

  • Vérifiez que l'application définit la stratégie d'autorisation de repli pour nécessiter l'authentification des utilisateurs.
  • Stockez le fichier statique en dehors de la racine web de l’application.
  • Après l’appel UseAuthorization, appelez UseStaticFiles, en spécifiant le chemin d’accès au dossier fichiers statiques en dehors de la racine web.

Espaces de noms pour les API suivantes :

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

Inscription du service :

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

Dans le pipeline de traitement des demandes après l’appel à UseAuthorization:

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

Espaces de noms pour les API suivantes :

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

Dans Startup.ConfigureServices :

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

Après Startup.Configure l’appel à UseAuthorization:

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

Dans le code précédent, la stratégie d’autorisation de secours nécessite des utilisateurs authentifiés. Les interfaces, telles que les contrôleurs et Razor pages, qui spécifient leurs propres exigences d’autorisation n’utilisent pas la stratégie d’autorisation de secours. Par exemple, les pages Razor, les contrôleurs ou les méthodes d'action avec [AllowAnonymous] ou [Authorize(PolicyName="MyPolicy")] utilisent l'attribut d'autorisation appliqué plutôt que la stratégie d'autorisation de repli.

RequireAuthenticatedUser ajoute DenyAnonymousAuthorizationRequirement à l’instance actuelle, ce qui impose l’authentification de l’utilisateur actuel.

Les ressources statiques stockées dans la racine web de l’application sont accessibles publiquement, car le middleware de fichier statique par défaut (UseStaticFiles) est appelé avant UseAuthorization. Les ressources statiques dans le SecureStaticFiles dossier nécessitent une authentification.

Une autre approche pour traiter les fichiers en fonction de l’autorisation consiste à :

  • Stockez les fichiers en dehors de la racine web et de tout répertoire accessible au middleware de fichiers statiques.
  • Servez les fichiers via une méthode d’action à laquelle l’autorisation est appliquée et retournez un FileResult objet.

À partir d’une Razor page (Pages/BannerImage.cshtml.cs) :

public class BannerImageModel : PageModel
{
    private readonly IWebHostEnvironment _env;

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

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

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

À partir d’un contrôleur (Controllers/HomeController.cs) :

[Authorize]
public IActionResult BannerImage()
{
    var filePath = Path.Combine(
        _env.ContentRootPath, "SecureStaticFiles", "images", "red-rose.jpg");

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

L’approche précédente nécessite une page ou un point de terminaison par fichier.

L’exemple de point de terminaison de routage suivant retourne des fichiers pour les utilisateurs authentifiés.

Dans le fichier Program :

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AuthenticatedUsers", b => b.RequireAuthenticatedUser());
});

...

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

    if (File.Exists(filePath))
    {
        return TypedResults.PhysicalFile(filePath, fileName);
    }

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

L’exemple de point de terminaison de routage suivant charge des fichiers pour les utilisateurs authentifiés dans le rôle d’administrateur («admin »).

Dans le fichier Program :

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminsOnly", b => b.RequireRole("admin"));
});

...

// IFormFile uses memory buffer for uploading. For handling large 
// files, use streaming instead. See the *File uploads* article
// in the ASP.NET Core documentation:
// https://learn.microsoft.com/aspnet/core/mvc/models/file-uploads
app.MapPost("/files", async (IFormFile file, LinkGenerator linker, 
    HttpContext context) =>
{
    // Don't rely on the value in 'file.FileName', as it's only metadata that can 
    // be manipulated by the end-user. Consider 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");

Dans Startup.ConfigureServices :

services.AddAuthorization(options =>
{
    options.AddPolicy("AuthenticatedUsers", b => b.RequireAuthenticatedUser());
});

Dans Startup.Configure :

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

    if (File.Exists(filePath))
    {
        return TypedResults.PhysicalFile(filePath, fileName);
    }

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

Le code suivant charge les fichiers pour les utilisateurs authentifiés dans le rôle d’administrateur («admin »).

Dans Startup.ConfigureServices :

services.AddAuthorization(options =>
{
    options.AddPolicy("AdminsOnly", b => b.RequireRole("admin"));
});

Dans Startup.Configure :

// IFormFile uses memory buffer for uploading. For handling large 
// files, use streaming instead. See the *File uploads* article
// in the ASP.NET Core documentation:
// https://learn.microsoft.com/aspnet/core/mvc/models/file-uploads
app.MapPost("/files", async (IFormFile file, LinkGenerator linker, 
    HttpContext context) =>
{
    // Don't rely on the value in 'file.FileName', as it's only metadata that can 
    // be manipulated by the end-user. Consider 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");

Navigation dans le répertoire

La navigation dans les répertoires permet d'afficher la liste des répertoires dans les répertoires spécifiés.

L’exploration des répertoires est désactivée par défaut pour des raisons de sécurité. Pour plus d’informations, consultez Considérations relatives à la sécurité des fichiers statiques.

Activez la navigation dans le répertoire avec l’API suivante :

Dans l’exemple suivant :

  • Un images dossier à la racine de l’application contient des images pour la navigation dans le répertoire.
  • Le chemin d’accès de la requête pour parcourir les images est /DirectoryImages.
  • L’appel de UseStaticFiles et la définition de FileProvider permettent d’afficher dans le navigateur des liens vers les fichiers individuels de StaticFileOptions.

Espaces de noms pour les API suivantes :

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

Inscription du service :

builder.Services.AddDirectoryBrowser();

Dans le pipeline de traitement des demandes après l’appel existant à MapStaticAssets (.NET 9 ou version ultérieure) ou UseStaticFiles (.NET 8 ou version antérieure) :

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

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

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

Espaces de noms pour les API suivantes :

using Microsoft.Extensions.FileProviders;
using System.IO;

Dans Startup.ConfigureServices :

services.AddDirectoryBrowser();

Dans Startup.Configure, après l’appel existant à UseStaticFiles:

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(env.WebRootPath, "images")),
    RequestPath = "/DirectoryImages"
});

app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(env.WebRootPath, "images")),
    RequestPath = "/DirectoryImages"
});

Le code précédent permet la navigation dans le répertoire wwwroot/images à l’aide de l’URL https://{HOST}/DirectoryImages avec des liens vers chaque fichier et dossier, où le {HOST} est l’hôte.

AddDirectoryBrowser ajoute les services requis par l’intergiciel de navigation d’annuaire, y compris HtmlEncoder. Ces services peuvent être ajoutés par d’autres appels, tels que AddRazorPages, mais nous vous recommandons d’appeler AddDirectoryBrowser pour vous assurer que les services sont ajoutés.

Délivrer des documents par défaut

La définition d’une page par défaut fournit aux visiteurs un point de départ sur un site. Pour servir un fichier par défaut à partir de wwwroot sans exiger que l'URL de la demande inclue le nom du fichier, appelez la méthode UseDefaultFiles.

UseDefaultFiles est un module de réécriture d’URL qui ne délivre pas le fichier. Dans le pipeline de traitement des demandes avant l’appel existant à MapStaticAssets (.NET 9 ou version ultérieure) ou UseStaticFiles (.NET 8 ou version antérieure) :

app.UseDefaultFiles();

Avec UseDefaultFiles, les demandes effectuées sur un dossier dans wwwroot recherchent :

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

Le premier fichier trouvé dans la liste est délivré comme si la demande incluait le nom du fichier. L’URL du navigateur continue de refléter l’URI demandé.

Le code suivant change le nom de fichier par défaut en default-document.html :

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

Combiner des fichiers statiques, des documents par défaut et une navigation dans le répertoire

UseFileServer combine les fonctionnalités de UseStaticFiles, de UseDefaultFiles et éventuellement de UseDirectoryBrowser.

Dans le pipeline de traitement des demandes après l’appel existant à MapStaticAssets (.NET 9 ou version ultérieure) ou UseStaticFiles (.NET 8 ou version antérieure), appel UseFileServer pour activer le service de fichiers statiques et le fichier par défaut :

app.UseFileServer();

La navigation dans le répertoire n’est pas activée pour l’exemple précédent.

Le code suivant active le service de fichiers statiques, le fichier par défaut et la navigation dans le répertoire.

Inscription du service :

builder.Services.AddDirectoryBrowser();

Dans le pipeline de traitement des demandes après l’appel existant à UseStaticFiles:

app.UseFileServer(enableDirectoryBrowsing: true);

Dans Startup.ConfigureServices :

services.AddDirectoryBrowser();

Dans Startup.Configure, après l’appel existant à UseStaticFiles:

app.UseFileServer(enableDirectoryBrowsing: true);

Pour l’adresse de l’hôte (/), UseFileServer retourne le document HTML par défaut avant la Page par défaut Razor ou la vue MVC par défaut Pages/Index.cshtmlHome/Index.cshtml.

Considérez la hiérarchie de répertoires suivante :

  • wwwroot
    • css
    • images
    • js
  • ExtraStaticFiles
    • images
      • logo.png
    • default.html

Le code suivant active le service des fichiers statiques, le fichier par défaut et la navigation dans ExtraStaticFilesle répertoire .

Espaces de noms pour les API suivantes :

using Microsoft.Extensions.FileProviders;

Inscription du service :

builder.Services.AddDirectoryBrowser();

Dans le pipeline de traitement des demandes après l’appel existant à UseStaticFiles:

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

Espaces de noms pour les API suivantes :

using Microsoft.Extensions.FileProviders;
using System.IO;

Dans Startup.ConfigureServices :

services.AddDirectoryBrowser();

Dans Startup.Configure, après l’appel existant à UseStaticFiles:

app.UseFileServer(new FileServerOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(env.ContentRootPath, "ExtraStaticFiles")),
    RequestPath = "/static-files",
    EnableDirectoryBrowsing = true
});

AddDirectoryBrowser doit être appelé quand la valeur de la propriété EnableDirectoryBrowsing est true.

Avec la hiérarchie de fichiers et le code précédents, les URL sont résolues comme indiqué dans le tableau suivant (le placeholder {HOST} est l’hôte).

URI Fichier de réponse
https://{HOST}/static-files/images/logo.png ExtraStaticFiles/images/logo.png
https://{HOST}/static-files ExtraStaticFiles/default.html

Si aucun fichier nommé par défaut n’existe dans le ExtraStaticFiles répertoire, https://{HOST}/static-files retourne la liste de répertoires avec des liens cliquables, où l’espace {HOST} réservé est l’hôte.

UseDefaultFiles et UseDirectoryBrowser effectuent une redirection côté client à partir de l’URI cible sans / de fin, vers l’URI cible avec un / de fin. Par exemple, de https://{HOST}/static-files (sans finale /) à https://{HOST}/static-files/ (comprend une finale /). Les URL relatives dans le répertoire ExtraStaticFiles ne sont pas valides sans barre oblique finale (/) à moins que l’option RedirectToAppendTrailingSlash de DefaultFilesOptions soit utilisée.

Associer les extensions de fichier aux types MIME

Note

Pour obtenir des conseils qui s’appliquent aux Blazor applications, consultez les fichiers statiques de ASP.NET CoreBlazor.

Utilisez FileExtensionContentTypeProvider.Mappings pour ajouter ou modifier les extensions de fichier dans les mappages des types de contenu MIME. Dans l’exemple suivant, plusieurs extensions de fichier sont mappées aux types MIME connus. L’extension .rtf est remplacée et .mp4 est supprimée :

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

...

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

Lorsque vous avez plusieurs options de fichier statique à configurer, vous pouvez également définir le fournisseur à l’aide de StaticFileOptions:

var provider = new FileExtensionContentTypeProvider();

...

builder.Services.Configure<StaticFileOptions>(options =>
{
    options.ContentTypeProvider = provider;
});

app.UseStaticFiles();

Dans Startup.Configure :

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 = "/images",
    ContentTypeProvider = provider
});

app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(env.WebRootPath, "images")),
    RequestPath = "/images"
});

Pour plus d’informations, consultez types de contenu MIME.

Types de contenu non standard

L’intergiciel de fichiers statiques comprend près de 400 types de contenu de fichier. Si l’utilisateur demande un fichier d’un type inconnu, l’intergiciel de fichiers statiques transmet la demande à l’intergiciel suivant dans le pipeline. Si aucun intergiciel ne gère la requête, une réponse 404 introuvable est retournée. Si l’exploration des répertoires est activée, un lien vers le fichier est affiché dans la liste de répertoires.

Le code suivant permet de servir des types de contenu inconnus et affiche le fichier inconnu en tant qu’image :

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

Avec le code précédent, une requête pour un fichier avec un type de contenu inconnu est retournée en tant qu’image.

Warning

L’activation de ServeUnknownFileTypes pose un problème de sécurité. Il est désactivé par défaut et son utilisation est déconseillée. Les extensions de fichier mappées aux types MIME offrent une alternative plus sûre au service de fichiers avec des extensions non standard.

Fournir un manifeste de fichiers statiques personnalisé

Si staticAssetsManifestPath c'est le cas avec null, IHostEnvironment.ApplicationName est utilisé pour localiser le manifeste. Vous pouvez également spécifier un chemin d’accès complet au fichier manifeste. Si un chemin relatif est utilisé, l’infrastructure recherche le fichier dans le AppContext.BaseDirectoryfichier .

Considérations de sécurité pour les fichiers statiques

Warning

UseDirectoryBrowser et UseStaticFiles peuvent entraîner une fuite de secrets. La désactivation de l’exploration de répertoires est fortement recommandée en production. Examinez attentivement les répertoires qui sont activés via UseStaticFiles ou UseDirectoryBrowser. L’ensemble du répertoire et de ses sous-répertoires deviennent accessibles publiquement. Stockez les fichiers qui peuvent être délivrés au public dans un répertoire dédié, comme <content_root>/wwwroot. Séparez ces fichiers des vues MVC, de Razor Pages, des fichiers de configuration, etc.

  • Les URL pour le contenu exposé avec UseDirectoryBrowser et UseStaticFiles sont soumises aux restrictions de respect de la casse et de caractères du système de fichiers sous-jacent. Par exemple, Windows est insensible à la casse, mais macOS et Linux ne le sont pas.

  • Les applications ASP.NET Core hébergées dans IIS utilisent le module ASP.NET Core pour transférer toutes les requêtes à l’application, notamment les requêtes de fichiers statiques. Le gestionnaire de fichiers statiques IIS n’est pas utilisé et n’a aucune chance de gérer les demandes.

  • Effectuez les étapes suivantes dans le Gestionnaire des services Internet (IIS) pour supprimer le gestionnaire de fichiers statiques d’IIS au niveau du serveur ou du site web :

    1. Accédez à la fonctionnalité Modules.
    2. Sélectionnez StaticFileModule dans la liste.
    3. Cliquez sur Supprimer dans l’encadré Actions.

Warning

Si le gestionnaire de fichiers statiques d’IIS est activé et que le module ASP.NET Core est incorrectement configuré, les fichiers statiques peuvent être délivrés. Cela se produit, par exemple, si le web.config fichier n’est pas déployé.

  • Placez les fichiers de code, y compris .cs et .cshtml, en dehors de la racine web du projet d’application. Par conséquent, une séparation logique est créée entre le contenu côté client et le code basé sur le serveur de l’application. Ceci empêche la fuite de code côté serveur.

Propriétés MSBuild

Les tableaux suivants montrent les propriétés et descriptions des métadonnées MSBuild des fichiers statiques.

Propriété Descriptif
EnableDefaultCompressedItems Active les modèles d’inclusion/exclusion de compression par défaut.
CompressionIncludePatterns Liste séparée par des points-virgules des modèles de fichier à inclure pour la compression.
CompressionExcludePatterns Liste séparée par des points-virgules des modèles de fichier à exclure de la compression.
EnableDefaultCompressionFormats Active les formats de compression par défaut (Gzip et Brotli).
BuildCompressionFormats Formats de compression à utiliser durant la compilation.
PublishCompressionFormats Formats de compression à utiliser pendant la publication.
DisableBuildCompression Désactive la compression pendant la compilation.
CompressDiscoveredAssetsDuringBuild Compresse les actifs découverts pendant la compilation.
BrotliCompressionLevel Niveau de compression pour l’algorithme Brotli.
StaticWebAssetBuildCompressAllAssets Compresse toutes les ressources pendant la compilation, pas seulement les ressources découvertes ou calculées au cours du processus de compilation.
StaticWebAssetPublishCompressAllAssets Compresse toutes les ressources pendant la publication, pas seulement les ressources découvertes ou calculées pendant une build.
Propriété Descriptif
StaticWebAssetBasePath Chemin d’URL de base pour toutes les ressources d’une bibliothèque.
StaticWebAssetsFingerprintContent Permet l'empreinte numérique du contenu pour briser la mise en cache.
StaticWebAssetFingerprintingEnabled Active la fonctionnalité d’empreinte digitale pour les ressources web statiques.
StaticWebAssetsCacheDefineStaticWebAssetsEnabled Active la mise en cache pour les définitions de ressources web statiques.
StaticWebAssetEndpointExclusionPattern Modèle d’exclusion des points de terminaison.
Groupe d’articles Descriptif Métadonnées
StaticWebAssetContentTypeMapping Associe les modèles de fichiers aux types de contenu et aux en-têtes de cache pour les points de terminaison. Pattern, Cache
StaticWebAssetFingerprintPattern Définit des modèles pour l'application d'empreintes à des ressources web statiques pour l'invalidation du cache. Pattern, Expression

Descriptions des métadonnées :

  • Pattern: modèle glob utilisé pour faire correspondre les fichiers. Pour StaticWebAssetContentTypeMapping, il correspond aux fichiers pour déterminer leur type de contenu (par exemple, *.js pour les fichiers JavaScript). Pour StaticWebAssetFingerprintPattern, il identifie les fichiers multi-extension qui nécessitent un traitement d’empreinte digitale spécial (par exemple, *.lib.module.js).

  • Cache: spécifie la valeur d’en-tête Cache-Control du type de contenu correspondant. Cela contrôle le comportement de mise en cache du navigateur (par exemple, max-age=3600, must-revalidate pour les fichiers multimédias).

  • Expression: définit la façon dont l’empreinte digitale est insérée dans le nom de fichier. La valeur par défaut est #[.{FINGERPRINT}], qui insère l’empreinte digitale ({FINGERPRINT} balise) avant l’extension.

L’exemple suivant associe le schéma de fichier bitmap (.bmp) au image/bmp type de contenu avec le paramètre de remplacement {CACHE HEADER} représentant l’en-tête Cache-Control à utiliser pour les points de terminaison non empreints :

<ItemGroup>
  <StaticWebAssetContentTypeMapping Include="image/bmp" Cache="{CACHE HEADER}" Pattern="*.bmp" />
</ItemGroup>

Options de configuration du runtime

Le tableau suivant décrit les options de configuration du runtime.

Clé de configuration Descriptif
ReloadStaticAssetsAtRuntime Active le rechargement à chaud pendant le développement des ressources statiques : sert des fichiers qui sont modifiés dans le répertoire racine du webwwwroot (recalcule ETag et recomprime si nécessaire) au lieu des versions du manifeste générées au moment de la construction. Par défaut, activé uniquement lors de la gestion d'un manifeste de build, sauf indication contraire explicite.
DisableStaticAssetNotFoundRuntimeFallback Lorsque true, il supprime l'endpoint de secours qui sert les fichiers nouvellement ajoutés et qui ne sont pas présents dans le manifeste de build. Lorsqu'il false est absent, une vérification d'existence de fichier {**path} en secours (GET/HEAD) enregistre un avertissement et sert le fichier avec un ETag calculé.
EnableStaticAssetsDevelopmentCaching Lorsqu'il est activé true, conserve les en-têtes d'origine Cache-Control sur les descripteurs de ressources. Lorsque false est présent ou absent, réécrit les en-têtes Cache-Control en no-cache afin d'éviter la mise en cache agressive du client pendant le développement.
EnableStaticAssetsDevelopmentIntegrity Lorsque true est activé, conserve les propriétés d'intégrité sur les descripteurs de ressources. Quand false ou absent, supprime toute propriété d’intégrité pour empêcher toute incompatibilité lorsque les fichiers changent pendant le développement.

Ressources supplémentaires