Fichiers statiques dans ASP.NET Core
Remarque
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.
Avertissement
Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la Stratégie de prise en charge de .NET et .NET Core. Pour la version actuelle, consultez la version .NET 8 de cet article.
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Pour la version actuelle, consultez la version .NET 8 de cet article.
Par Rick Anderson
Les fichiers statiques, comme les fichiers HTML, CSS, images et JavaScript, sont des ressources qu’une application ASP.NET Core délivre directement aux clients, par défaut.
Pour obtenir des instructions sur les fichiers statiques Blazor, en complément ou en remplacement des instructions de cet article, consultez Fichiers statiques Blazor ASP.NET Core.
Délivrer des fichiers statiques
Les fichiers statiques sont stockés dans le répertoire racine web du projet. Le répertoire par défaut est {content root}/wwwroot
, mais il peut être modifié avec la méthode UseWebRoot. Pour plus d’informations, consultez Racine de contenu et Racine web.
La méthode CreateBuilder définit le répertoire actif comme racine du contenu :
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();
Les fichiers statiques sont accessibles via un chemin relatif à la racine web. Par exemple, les modèles de projet Application web contiennent plusieurs dossiers dans le dossier wwwroot
:
wwwroot
css
js
lib
Considérez une application avec le fichier wwwroot/images/MyImage.jpg
. Le format URI pour accéder à un fichier dans le dossier images
est https://<hostname>/images/<image_file_name>
. Par exemple, https://localhost:5001/images/MyImage.jpg
MapStaticAssets
La création d’applications web performantes nécessite l’optimisation de la remise des ressources au navigateur. Les optimisations possibles sont les suivantes :
- Servir une seule fois une ressource donnée tant que le fichier ne change pas ou que le navigateur n’efface pas son cache. Définissez l’en-tête ETag.
- Empêchez le navigateur d’utiliser des ressources anciennes ou obsolètes après la mise à jour d’une application. Définissez l’en-tête Last-Modified.
- Configurez les en-têtes de mise en cache appropriés.
- Utilisez un intergiciel de mise en cache.
- Servez des versions compressées des ressources lorsque cela est possible.
- Utilisez un CDN pour servir les ressources à proximité de l’utilisateur.
- Réduire la taille des ressources servies au navigateur. Cette optimisation n’inclut pas la minification.
MapStaticAssets sont des conventions de point de terminaison de routage qui optimisent la remise des ressources statiques dans une application. Il est conçu pour fonctionner avec toutes les infrastructures d’interface utilisateur, notamment Blazor, Razor Pages et MVC.
UseStaticFiles
sert également des fichiers statiques, mais il ne fournit pas le même niveau d’optimisation que MapStaticAssets
. Pour une comparaison entre UseStaticFiles
et MapStaticAssets
, consultez Optimisation de la remise des ressources web statiques.
Délivrer des fichiers à la racine web
Les modèles d’application web par défaut appellent la méthode MapStaticAssets dans Program.cs
, ce qui permet de délivrer les fichiers statiques :
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();
La surcharge de la méthode UseStaticFiles
sans paramètres marque les fichiers à la racine web comme étant délivrables. Le balisage suivant référence wwwroot/images/MyImage.jpg
:
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
Dans le balisage précédent, le caractère tilde ~
pointe vers la racine web.
Délivrer des fichiers en dehors de la racine web
Considérez une hiérarchie de répertoires dans laquelle les fichiers statiques à délivrer se trouvent en dehors de la racine web :
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
Une demande peut accéder au fichier red-rose.jpg
en configurant l’intergiciel de fichiers statiques comme suit :
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();
Dans le code précédent, la hiérarchie de répertoires MyStaticFiles est exposée publiquement via le segment d’URI StaticFiles. Une demande à https://<hostname>/StaticFiles/images/red-rose.jpg
délivre le fichier red-rose.jpg
.
Le balisage suivant référence MyStaticFiles/images/red-rose.jpg
:
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
Pour délivrer des fichiers à partir de plusieurs emplacements, consultez Délivrer des fichiers à partir de plusieurs emplacements.
Définir des en-têtes de réponse HTTP
Un objet StaticFileOptions peut être utilisé pour définir des en-têtes de réponse HTTP. En plus de configurer la possibilité de délivrer des fichiers statiques à partir de la racine web, le code suivant définit l’en-tête Cache-Control :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var cacheMaxAgeOneWeek = (60 * 60 * 24 * 7).ToString();
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers.Append(
"Cache-Control", $"public, max-age={cacheMaxAgeOneWeek}");
}
});
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
Le code précédent rend les fichiers statiques accessibles publiquement dans le cache local pendant une semaine.
Autorisations des fichiers statiques
Les modèles ASP.NET Core appellent MapStaticAssets 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 délivrés par l’intergiciel de fichiers statiques, tels que ceux sous
wwwroot
, sont accessibles publiquement.
Pour délivrer des fichiers statiques en fonction d’une autorisation :
- Stockez-les en dehors de
wwwroot
. - Appelez
UseStaticFiles
, en spécifiant un chemin, après avoir appeléUseAuthorization
. - Définissez la stratégie d’autorisation de secours.
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();
Dans le code précédent, la stratégie d’autorisation de secours exige que tous les utilisateurs soient authentifiés. Les points de terminaison tels que les contrôleurs, Razor Pages, etc., qui spécifient leurs propres exigences d’autorisation, n’utilisent pas la stratégie d’autorisation de secours. Par exemple, Razor Pages, 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 secours.
RequireAuthenticatedUser ajoute DenyAnonymousAuthorizationRequirement à l’instance actuelle, ce qui impose l’authentification de l’utilisateur actuel.
Les ressources statiques sous wwwroot
sont accessibles publiquement, car l’intergiciel de fichiers statiques par défaut (app.UseStaticFiles();
) est appelé avant UseAuthentication
. Les ressources statiques figurant dans le dossier MyStaticFiles nécessitent une authentification. Cet exemple de code illustre ceci.
Une autre approche pour traiter les fichiers en fonction de l’autorisation consiste à :
Les stocker en dehors de
wwwroot
et de tout répertoire accessible à l’intergiciel de fichiers statiques.Les délivrer via une méthode d’action à laquelle une autorisation est appliquée et à retourner un objet FileResult :
[Authorize] public class BannerImageModel : PageModel { private readonly IWebHostEnvironment _env; public BannerImageModel(IWebHostEnvironment env) => _env = env; public PhysicalFileResult OnGet() { var filePath = Path.Combine( _env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg"); return PhysicalFile(filePath, "image/jpeg"); } }
L’approche précédente nécessite une page ou un point de terminaison par fichier. Le code suivant retourne des fichiers ou charge des fichiers pour les utilisateurs authentifiés :
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 dans l’exemple précédent utilise la mémoire tampon pour le chargement. Pour les fichiers volumineux, utilisez la diffusion en continu. Consultez Chargement de fichiers volumineux avec diffusion en continu.
Pour obtenir l’exemple complet, consultez le dossier GitHub StaticFileAuth.
Exploration de répertoires
La navigation dans les répertoires permet de lister les 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 l’exploration des répertoires avec AddDirectoryBrowser et 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();
Le code précédent permet l’exploration des répertoires du dossier wwwroot/images en utilisant l’URL https://<hostname>/MyImages
, avec des liens vers chaque fichier et dossier :
AddDirectoryBrowser
ajoute les services nécessaires pour l’intergiciel d’exploration des répertoires, notamment HtmlEncoder. Ces services peuvent être ajoutés par d’autres appels, tels que AddRazorPages, mais nous vous recommandons d’appeler AddDirectoryBrowser
pour garantir que les services sont ajoutés dans toutes les applications.
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 délivrer 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 :
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
doit être appelé avant UseStaticFiles
pour délivrer le fichier par défaut. UseDefaultFiles
est un module de réécriture d’URL qui ne délivre pas le fichier.
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é. Par exemple, dans l’exemple d’application, une demande à https://localhost:<port>/def/
renvoie default.html
à partir de wwwroot/def
.
Le code suivant change le nom de fichier par défaut en mydefault.html
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
UseFileServer pour les documents par défaut
UseFileServer combine les fonctionnalités de UseStaticFiles
, de UseDefaultFiles
et éventuellement de UseDirectoryBrowser
.
Appelez app.UseFileServer
pour activer la possibilité de délivrer des fichiers statiques et le fichier par défaut. L’exploration des répertoires n’est pas activée :
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();
Le code suivant active la possibilité de délivrer des fichiers statiques, le fichier par défaut et l’exploration des répertoires :
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();
Considérez la hiérarchie de répertoires suivante :
wwwroot
css
images
js
MyStaticFiles
defaultFiles
default.html
image3.png
images
MyImage.jpg
Le code suivant active la possibilité de délivrer des fichiers statiques, le fichier par défaut et l’exploration des répertoires de MyStaticFiles
:
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles",
EnableDirectoryBrowsing = true
});
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
AddDirectoryBrowser doit être appelé quand la valeur de la propriété EnableDirectoryBrowsing
est true
.
En utilisant la hiérarchie de fichiers et le code précédents, les URL sont résolues comme suit :
URI | Response |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
Liste de répertoires |
https://<hostname>/StaticFiles/defaultFiles |
MyStaticFiles/defaultFiles/default.html |
https://<hostname>/StaticFiles/defaultFiles/image3.png |
MyStaticFiles/defaultFiles//image3.png |
Si aucun fichier nommé par défaut n’existe dans le répertoire MyStaticFiles, https://<hostname>/StaticFiles
retourne la liste des répertoires avec des liens interactifs :
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://<hostname>/StaticFiles
à https://<hostname>/StaticFiles/
. Les URL relatives au sein du répertoire StaticFiles ne sont pas valides sans barre oblique de fin (/
) à moins que l’option RedirectToAppendTrailingSlash de DefaultFilesOptions soit utilisée.
FileExtensionContentTypeProvider
La classe FileExtensionContentTypeProvider contient une propriété Mappages qui agit comme un mappage des extensions de fichiers à des types de contenu MIME. Dans l’exemple suivant, plusieurs extensions de fichiers sont mappées à des types MIME connus. L’extension .rtf est remplacée et l’extension .mp4 est supprimée :
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();
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 délivrer des types inconnus et rend le fichier inconnu en tant qu’image :
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();
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.
Avertissement
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. FileExtensionContentTypeProvider fournit une alternative plus sûre pour délivrer des fichiers avec des extensions non standard.
Délivrer des fichiers à partir de plusieurs emplacements
Considérez la page Razor suivante qui affiche le fichier /MyStaticFiles/image3.png
:
@page
<p> Test /MyStaticFiles/image3.png</p>
<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">
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. L’exemple suivant appelle UseStaticFiles
deux fois pour délivrer des fichiers à partir de wwwroot
et de MyStaticFiles
:
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});
Utilisation du code précédent :
- Le fichier
/MyStaticFiles/image3.png
est affiché. - Le Tag Helper d’imageAppendVersion n’est pas appliqué, car les Tag Helpers dépendent de WebRootFileProvider.
WebRootFileProvider
n’a pas été mis à jour pour inclure le dossierMyStaticFiles
.
Le code suivant met à jour WebRootFileProvider
, qui permet au Tag Helper d’image de fournir une version :
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();
Remarque
L’approche précédente s’applique aux applications Razor Pages et MVC. Pour obtenir de l’aide qui s’applique aux Blazor Web App, consultez Fichiers statiques Blazor ASP.NET Core.
Considérations de sécurité pour les fichiers statiques
Avertissement
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
,UseStaticFiles
etMapStaticAssets
sont soumises aux restrictions de respect de la casse et des caractères du système de fichiers sous-jacent. Par exemple, Windows ne respecte pas la casse, mais macOS et Linux la respectent.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 :
- Accédez à la fonctionnalité Modules.
- Sélectionnez StaticFileModule dans la liste.
- Cliquez sur Supprimer dans l’encadré Actions.
Avertissement
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 fichier web.config 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.
Délivrez des fichiers en dehors de wwwroot en mettant à jour IWebHostEnvironment.WebRootPath
Quand IWebHostEnvironment.WebRootPath est défini sur un dossier autre que wwwroot
:
- Dans l’environnement de développement, les ressources statiques trouvées dans
wwwroot
et dans la mise à jour deIWebHostEnvironment.WebRootPath
sont délivrées à partir dewwwroot
. - Dans tout environnement autre que celui de développement, les ressources statiques en double sont délivrées à partir du dossier
IWebHostEnvironment.WebRootPath
mis à jour.
Considérez une application web créée avec le modèle web vide :
Contenant un fichier
Index.html
danswwwroot
etwwwroot-custom
.Avec le fichier
Program.cs
mis à jour suivant qui définitWebRootPath = "wwwroot-custom"
:var builder = WebApplication.CreateBuilder(new WebApplicationOptions { Args = args, // Look for static files in "wwwroot-custom" WebRootPath = "wwwroot-custom" }); var app = builder.Build(); app.UseDefaultFiles(); app.MapStaticAssets(); app.Run();
Dans le code précédent, les demandes adressées à /
:
- Dans l’environnement de développement, retournent
wwwroot/Index.html
- Dans tout environnement autre que celui de développement, retournent
wwwroot-custom/Index.html
Pour vous assurer que les ressources à partir de wwwroot-custom
sont retournées, utilisez l’une des approches suivantes :
Supprimez les ressources nommées en double dans
wwwroot
.Définissez
"ASPNETCORE_ENVIRONMENT"
dansProperties/launchSettings.json
sur n’importe quelle valeur autre que"Development"
.Désactivez complètement les ressources web statiques en définissant
<StaticWebAssetsEnabled>false</StaticWebAssetsEnabled>
dans le fichier projet. AVERTISSEMENT, la désactivation des ressources web statiques désactive les bibliothèques de classes Razor.Ajoutez le XML suivant au fichier de projet :
<ItemGroup> <Content Remove="wwwroot\**" /> </ItemGroup>
Le code suivant met à jour IWebHostEnvironment.WebRootPath
vers une valeur de non-développement, garantissant que le contenu en double est retourné à partir de wwwroot-custom
plutôt que wwwroot
:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Examine Hosting environment: logging value
EnvironmentName = Environments.Staging,
WebRootPath = "wwwroot-custom"
});
var app = builder.Build();
app.Logger.LogInformation("ASPNETCORE_ENVIRONMENT: {env}",
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));
app.Logger.LogInformation("app.Environment.IsDevelopment(): {env}",
app.Environment.IsDevelopment().ToString());
app.UseDefaultFiles();
app.MapStaticAssets();
app.Run();
Ressources supplémentaires
Par Rick Anderson
Les fichiers statiques, comme les fichiers HTML, CSS, images et JavaScript, sont des ressources qu’une application ASP.NET Core délivre directement aux clients, par défaut.
Délivrer des fichiers statiques
Les fichiers statiques sont stockés dans le répertoire racine web du projet. Le répertoire par défaut est {content root}/wwwroot
, mais il peut être modifié avec la méthode UseWebRoot. Pour plus d’informations, consultez Racine de contenu et Racine web.
La méthode CreateBuilder définit le répertoire actif comme racine du contenu :
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();
Les fichiers statiques sont accessibles via un chemin relatif à la racine web. Par exemple, les modèles de projet Application web contiennent plusieurs dossiers dans le dossier wwwroot
:
wwwroot
css
js
lib
Envisagez de créer le dossier wwwroot/images et d’ajouter le fichier wwwroot/images/MyImage.jpg
. Le format URI pour accéder à un fichier dans le dossier images
est https://<hostname>/images/<image_file_name>
. Par exemple, https://localhost:5001/images/MyImage.jpg
Délivrer des fichiers à la racine web
Les modèles d’application web par défaut appellent la méthode UseStaticFiles dans Program.cs
, ce qui permet de délivrer les fichiers statiques :
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();
La surcharge de la méthode UseStaticFiles
sans paramètres marque les fichiers à la racine web comme étant délivrables. Le balisage suivant référence wwwroot/images/MyImage.jpg
:
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
Dans le balisage précédent, le caractère tilde ~
pointe vers la racine web.
Délivrer des fichiers en dehors de la racine web
Considérez une hiérarchie de répertoires dans laquelle les fichiers statiques à délivrer se trouvent en dehors de la racine web :
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
Une demande peut accéder au fichier red-rose.jpg
en configurant l’intergiciel de fichiers statiques comme suit :
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();
Dans le code précédent, la hiérarchie de répertoires MyStaticFiles est exposée publiquement via le segment d’URI StaticFiles. Une demande à https://<hostname>/StaticFiles/images/red-rose.jpg
délivre le fichier red-rose.jpg
.
Le balisage suivant référence MyStaticFiles/images/red-rose.jpg
:
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
Pour délivrer des fichiers à partir de plusieurs emplacements, consultez Délivrer des fichiers à partir de plusieurs emplacements.
Définir des en-têtes de réponse HTTP
Un objet StaticFileOptions peut être utilisé pour définir des en-têtes de réponse HTTP. En plus de configurer la possibilité de délivrer des fichiers statiques à partir de la racine web, le code suivant définit l’en-tête Cache-Control :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var cacheMaxAgeOneWeek = (60 * 60 * 24 * 7).ToString();
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers.Append(
"Cache-Control", $"public, max-age={cacheMaxAgeOneWeek}");
}
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
Le code précédent rend les fichiers statiques accessibles publiquement dans le cache local pendant une semaine (604800 secondes).
Autorisations des fichiers statiques
Les modèles ASP.NET Core appellent 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 délivrés par l’intergiciel de fichiers statiques, tels que ceux sous
wwwroot
, sont accessibles publiquement.
Pour délivrer des fichiers statiques en fonction d’une autorisation :
- Stockez-les en dehors de
wwwroot
. - Appelez
UseStaticFiles
, en spécifiant un chemin, après avoir appeléUseAuthorization
. - Définissez la stratégie d’autorisation de secours.
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();
Dans le code précédent, la stratégie d’autorisation de secours exige que tous les utilisateurs soient authentifiés. Les points de terminaison tels que les contrôleurs, Razor Pages, etc., qui spécifient leurs propres exigences d’autorisation, n’utilisent pas la stratégie d’autorisation de secours. Par exemple, Razor Pages, 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 secours.
RequireAuthenticatedUser ajoute DenyAnonymousAuthorizationRequirement à l’instance actuelle, ce qui impose l’authentification de l’utilisateur actuel.
Les ressources statiques sous wwwroot
sont accessibles publiquement, car l’intergiciel de fichiers statiques par défaut (app.UseStaticFiles();
) est appelé avant UseAuthentication
. Les ressources statiques figurant dans le dossier MyStaticFiles nécessitent une authentification. Cet exemple de code illustre ceci.
Une autre approche pour traiter les fichiers en fonction de l’autorisation consiste à :
Les stocker en dehors de
wwwroot
et de tout répertoire accessible à l’intergiciel de fichiers statiques.Les délivrer via une méthode d’action à laquelle une autorisation est appliquée et à retourner un objet FileResult :
[Authorize] public class BannerImageModel : PageModel { private readonly IWebHostEnvironment _env; public BannerImageModel(IWebHostEnvironment env) => _env = env; public PhysicalFileResult OnGet() { var filePath = Path.Combine( _env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg"); return PhysicalFile(filePath, "image/jpeg"); } }
L’approche précédente nécessite une page ou un point de terminaison par fichier. Le code suivant retourne des fichiers ou charge des fichiers pour les utilisateurs authentifiés :
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();
Pour obtenir l’exemple complet, consultez le dossier GitHub StaticFileAuth.
Exploration de répertoires
La navigation dans les répertoires permet de lister les 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 l’exploration des répertoires avec AddDirectoryBrowser et 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();
Le code précédent permet l’exploration des répertoires du dossier wwwroot/images en utilisant l’URL https://<hostname>/MyImages
, avec des liens vers chaque fichier et dossier :
AddDirectoryBrowser
ajoute les services nécessaires pour l’intergiciel d’exploration des répertoires, notamment HtmlEncoder. Ces services peuvent être ajoutés par d’autres appels, tels que AddRazorPages, mais nous vous recommandons d’appeler AddDirectoryBrowser
pour garantir que les services sont ajoutés dans toutes les applications.
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 délivrer 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 :
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
doit être appelé avant UseStaticFiles
pour délivrer le fichier par défaut. UseDefaultFiles
est un module de réécriture d’URL qui ne délivre pas le fichier.
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 mydefault.html
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
UseFileServer pour les documents par défaut
UseFileServer combine les fonctionnalités de UseStaticFiles
, de UseDefaultFiles
et éventuellement de UseDirectoryBrowser
.
Appelez app.UseFileServer
pour activer la possibilité de délivrer des fichiers statiques et le fichier par défaut. L’exploration des répertoires n’est pas activée :
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();
Le code suivant active la possibilité de délivrer des fichiers statiques, le fichier par défaut et l’exploration des répertoires :
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();
Considérez la hiérarchie de répertoires suivante :
wwwroot
css
images
js
MyStaticFiles
images
MyImage.jpg
default.html
Le code suivant active la possibilité de délivrer des fichiers statiques, le fichier par défaut et l’exploration des répertoires de MyStaticFiles
:
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles",
EnableDirectoryBrowsing = true
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
AddDirectoryBrowser doit être appelé quand la valeur de la propriété EnableDirectoryBrowsing
est true
.
En utilisant la hiérarchie de fichiers et le code précédents, les URL sont résolues comme suit :
URI | Response |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
MyStaticFiles/default.html |
Si aucun fichier nommé par défaut n’existe dans le répertoire MyStaticFiles, https://<hostname>/StaticFiles
retourne la liste des répertoires avec des liens interactifs :
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://<hostname>/StaticFiles
à https://<hostname>/StaticFiles/
. Les URL relatives au sein du répertoire StaticFiles ne sont pas valides sans barre oblique de fin (/
) à moins que l’option RedirectToAppendTrailingSlash de DefaultFilesOptions soit utilisée.
FileExtensionContentTypeProvider
La classe FileExtensionContentTypeProvider contient une propriété Mappings
qui agit comme un mappage des extensions de fichiers à des types de contenu MIME. Dans l’exemple suivant, plusieurs extensions de fichiers sont mappées à des types MIME connus. L’extension .rtf est remplacée et l’extension .mp4 est supprimée :
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();
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 délivrer des types inconnus et rend le fichier inconnu en tant qu’image :
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();
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.
Avertissement
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. FileExtensionContentTypeProvider fournit une alternative plus sûre pour délivrer des fichiers avec des extensions non standard.
Délivrer des fichiers à partir de plusieurs emplacements
Considérez la page Razor suivante qui affiche le fichier /MyStaticFiles/image3.png
:
@page
<p> Test /MyStaticFiles/image3.png</p>
<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">
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. L’exemple suivant appelle UseStaticFiles
deux fois pour délivrer des fichiers à partir de wwwroot
et de MyStaticFiles
:
app.UseStaticFiles(); // Serve files from wwwroot
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});
Utilisation du code précédent :
- Le fichier
/MyStaticFiles/image3.png
est affiché. - Le Tag Helper d’imageAppendVersion n’est pas appliqué, car les Tag Helpers dépendent de WebRootFileProvider.
WebRootFileProvider
n’a pas été mis à jour pour inclure le dossierMyStaticFiles
.
Le code suivant met à jour WebRootFileProvider
, qui permet au Tag Helper d’image de fournir une version :
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();
Remarque
L’approche précédente s’applique aux applications Razor Pages et MVC. Pour obtenir de l’aide qui s’applique aux Blazor Web App, consultez Fichiers statiques Blazor ASP.NET Core.
Considérations de sécurité pour les fichiers statiques
Avertissement
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
etUseStaticFiles
sont soumises aux restrictions de respect de la casse et de caractères du système de fichiers sous-jacent. Par exemple, Windows ne respecte pas la casse, mais macOS et Linux la respectent.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 :
- Accédez à la fonctionnalité Modules.
- Sélectionnez StaticFileModule dans la liste.
- Cliquez sur Supprimer dans l’encadré Actions.
Avertissement
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 fichier web.config 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.
Délivrez des fichiers en dehors de wwwroot en mettant à jour IWebHostEnvironment.WebRootPath
Quand IWebHostEnvironment.WebRootPath est défini sur un dossier autre que wwwroot
:
- Dans l’environnement de développement, les ressources statiques trouvées dans
wwwroot
et dans la mise à jour deIWebHostEnvironment.WebRootPath
sont délivrées à partir dewwwroot
. - Dans tout environnement autre que celui de développement, les ressources statiques en double sont délivrées à partir du dossier
IWebHostEnvironment.WebRootPath
mis à jour.
Considérez une application web créée avec le modèle web vide :
Contenant un fichier
Index.html
danswwwroot
etwwwroot-custom
.Avec le fichier
Program.cs
mis à jour suivant qui définitWebRootPath = "wwwroot-custom"
:var builder = WebApplication.CreateBuilder(new WebApplicationOptions { Args = args, // Look for static files in "wwwroot-custom" WebRootPath = "wwwroot-custom" }); var app = builder.Build(); app.UseDefaultFiles(); app.UseStaticFiles(); app.Run();
Dans le code précédent, les demandes adressées à /
:
- Dans l’environnement de développement, retournent
wwwroot/Index.html
- Dans tout environnement autre que celui de développement, retournent
wwwroot-custom/Index.html
Pour vous assurer que les ressources à partir de wwwroot-custom
sont retournées, utilisez l’une des approches suivantes :
Supprimez les ressources nommées en double dans
wwwroot
.Définissez
"ASPNETCORE_ENVIRONMENT"
dansProperties/launchSettings.json
sur n’importe quelle valeur autre que"Development"
.Désactivez complètement les ressources web statiques en définissant
<StaticWebAssetsEnabled>false</StaticWebAssetsEnabled>
dans le fichier projet. AVERTISSEMENT, la désactivation des ressources web statiques désactive les bibliothèques de classes Razor.Ajoutez le code JSON suivant au fichier projet :
<ItemGroup> <Content Remove="wwwroot\**" /> </ItemGroup>
Le code suivant met à jour IWebHostEnvironment.WebRootPath
vers une valeur de non-développement, garantissant que le contenu en double est retourné à partir de wwwroot-custom
plutôt que wwwroot
:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Examine Hosting environment: logging value
EnvironmentName = Environments.Staging,
WebRootPath = "wwwroot-custom"
});
var app = builder.Build();
app.Logger.LogInformation("ASPNETCORE_ENVIRONMENT: {env}",
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));
app.Logger.LogInformation("app.Environment.IsDevelopment(): {env}",
app.Environment.IsDevelopment().ToString());
app.UseDefaultFiles();
app.UseStaticFiles();
app.Run();
Ressources supplémentaires
Par Rick Anderson et Kirk Larkin
Les fichiers statiques, comme les fichiers HTML, CSS, images et JavaScript, sont des ressources qu’une application ASP.NET Core délivre directement aux clients, par défaut.
Délivrer des fichiers statiques
Les fichiers statiques sont stockés dans le répertoire racine web du projet. Le répertoire par défaut est {content root}/wwwroot
, mais il peut être modifié avec la méthode UseWebRoot. Pour plus d’informations, consultez Racine de contenu et Racine web.
La méthode CreateBuilder définit le répertoire actif comme racine du contenu :
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();
Les fichiers statiques sont accessibles via un chemin relatif à la racine web. Par exemple, les modèles de projet Application web contiennent plusieurs dossiers dans le dossier wwwroot
:
wwwroot
css
js
lib
Envisagez de créer le dossier wwwroot/images et d’ajouter le fichier wwwroot/images/MyImage.jpg
. Le format URI pour accéder à un fichier dans le dossier images
est https://<hostname>/images/<image_file_name>
. Par exemple, https://localhost:5001/images/MyImage.jpg
Délivrer des fichiers à la racine web
Les modèles d’application web par défaut appellent la méthode UseStaticFiles dans Program.cs
, ce qui permet de délivrer les fichiers statiques :
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();
La surcharge de la méthode UseStaticFiles
sans paramètres marque les fichiers à la racine web comme étant délivrables. Le balisage suivant référence wwwroot/images/MyImage.jpg
:
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
Dans le balisage précédent, le caractère tilde ~
pointe vers la racine web.
Délivrer des fichiers en dehors de la racine web
Considérez une hiérarchie de répertoires dans laquelle les fichiers statiques à délivrer se trouvent en dehors de la racine web :
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
Une demande peut accéder au fichier red-rose.jpg
en configurant l’intergiciel de fichiers statiques comme suit :
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();
Dans le code précédent, la hiérarchie de répertoires MyStaticFiles est exposée publiquement via le segment d’URI StaticFiles. Une demande à https://<hostname>/StaticFiles/images/red-rose.jpg
délivre le fichier red-rose.jpg
.
Le balisage suivant référence MyStaticFiles/images/red-rose.jpg
:
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
Pour délivrer des fichiers à partir de plusieurs emplacements, consultez Délivrer des fichiers à partir de plusieurs emplacements.
Définir des en-têtes de réponse HTTP
Un objet StaticFileOptions peut être utilisé pour définir des en-têtes de réponse HTTP. En plus de configurer la possibilité de délivrer des fichiers statiques à partir de la racine web, le code suivant définit l’en-tête Cache-Control :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var cacheMaxAgeOneWeek = (60 * 60 * 24 * 7).ToString();
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers.Append(
"Cache-Control", $"public, max-age={cacheMaxAgeOneWeek}");
}
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
Le code précédent rend les fichiers statiques accessibles publiquement dans le cache local pendant une semaine (604800 secondes).
Autorisations des fichiers statiques
Les modèles ASP.NET Core appellent 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 délivrés par l’intergiciel de fichiers statiques, tels que ceux sous
wwwroot
, sont accessibles publiquement.
Pour délivrer des fichiers statiques en fonction d’une autorisation :
- Stockez-les en dehors de
wwwroot
. - Appelez
UseStaticFiles
, en spécifiant un chemin, après avoir appeléUseAuthorization
. - Définissez la stratégie d’autorisation de secours.
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();
Dans le code précédent, la stratégie d’autorisation de secours exige que tous les utilisateurs soient authentifiés. Les points de terminaison tels que les contrôleurs, Razor Pages, etc., qui spécifient leurs propres exigences d’autorisation, n’utilisent pas la stratégie d’autorisation de secours. Par exemple, Razor Pages, 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 secours.
RequireAuthenticatedUser ajoute DenyAnonymousAuthorizationRequirement à l’instance actuelle, ce qui impose l’authentification de l’utilisateur actuel.
Les ressources statiques sous wwwroot
sont accessibles publiquement, car l’intergiciel de fichiers statiques par défaut (app.UseStaticFiles();
) est appelé avant UseAuthentication
. Les ressources statiques figurant dans le dossier MyStaticFiles nécessitent une authentification. Cet exemple de code illustre ceci.
Une autre approche pour traiter les fichiers en fonction de l’autorisation consiste à :
- Les stocker en dehors de
wwwroot
et de tout répertoire accessible à l’intergiciel de fichiers statiques. - Les délivrer via une méthode d’action à laquelle une autorisation est appliquée et à retourner un objet FileResult :
[Authorize]
public class BannerImageModel : PageModel
{
private readonly IWebHostEnvironment _env;
public BannerImageModel(IWebHostEnvironment env) =>
_env = env;
public PhysicalFileResult OnGet()
{
var filePath = Path.Combine(
_env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");
return PhysicalFile(filePath, "image/jpeg");
}
}
Exploration de répertoires
La navigation dans les répertoires permet de lister les 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 l’exploration des répertoires avec AddDirectoryBrowser et 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();
Le code précédent permet l’exploration des répertoires du dossier wwwroot/images en utilisant l’URL https://<hostname>/MyImages
, avec des liens vers chaque fichier et dossier :
AddDirectoryBrowser
ajoute les services nécessaires pour l’intergiciel d’exploration des répertoires, notamment HtmlEncoder. Ces services peuvent être ajoutés par d’autres appels, tels que AddRazorPages, mais nous vous recommandons d’appeler AddDirectoryBrowser
pour garantir que les services sont ajoutés dans toutes les applications.
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 délivrer 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 :
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
doit être appelé avant UseStaticFiles
pour délivrer le fichier par défaut. UseDefaultFiles
est un module de réécriture d’URL qui ne délivre pas le fichier.
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 mydefault.html
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
UseFileServer pour les documents par défaut
UseFileServer combine les fonctionnalités de UseStaticFiles
, de UseDefaultFiles
et éventuellement de UseDirectoryBrowser
.
Appelez app.UseFileServer
pour activer la possibilité de délivrer des fichiers statiques et le fichier par défaut. L’exploration des répertoires n’est pas activée :
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();
Le code suivant active la possibilité de délivrer des fichiers statiques, le fichier par défaut et l’exploration des répertoires :
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();
Considérez la hiérarchie de répertoires suivante :
wwwroot
css
images
js
MyStaticFiles
images
MyImage.jpg
default.html
Le code suivant active la possibilité de délivrer des fichiers statiques, le fichier par défaut et l’exploration des répertoires de MyStaticFiles
:
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles",
EnableDirectoryBrowsing = true
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
AddDirectoryBrowser doit être appelé quand la valeur de la propriété EnableDirectoryBrowsing
est true
.
En utilisant la hiérarchie de fichiers et le code précédents, les URL sont résolues comme suit :
URI | Response |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
MyStaticFiles/default.html |
Si aucun fichier nommé par défaut n’existe dans le répertoire MyStaticFiles, https://<hostname>/StaticFiles
retourne la liste des répertoires avec des liens interactifs :
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://<hostname>/StaticFiles
à https://<hostname>/StaticFiles/
. Les URL relatives au sein du répertoire StaticFiles ne sont pas valides sans barre oblique de fin (/
) à moins que l’option RedirectToAppendTrailingSlash de DefaultFilesOptions soit utilisée.
FileExtensionContentTypeProvider
La classe FileExtensionContentTypeProvider contient une propriété Mappings
qui agit comme un mappage des extensions de fichiers à des types de contenu MIME. Dans l’exemple suivant, plusieurs extensions de fichiers sont mappées à des types MIME connus. L’extension .rtf est remplacée et l’extension .mp4 est supprimée :
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();
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 délivrer des types inconnus et rend le fichier inconnu en tant qu’image :
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();
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.
Avertissement
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. FileExtensionContentTypeProvider fournit une alternative plus sûre pour délivrer des fichiers avec des extensions non standard.
Délivrer des fichiers à partir de plusieurs emplacements
Considérez la page Razor suivante qui affiche le fichier /MyStaticFiles/image3.png
:
@page
<p> Test /MyStaticFiles/image3.png</p>
<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">
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. L’exemple suivant appelle UseStaticFiles
deux fois pour délivrer des fichiers à partir de wwwroot
et de MyStaticFiles
:
app.UseStaticFiles(); // Serve files from wwwroot
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});
Utilisation du code précédent :
- Le fichier
/MyStaticFiles/image3.png
est affiché. - Le Tag Helper d’imageAppendVersion n’est pas appliqué, car les Tag Helpers dépendent de WebRootFileProvider.
WebRootFileProvider
n’a pas été mis à jour pour inclure le dossierMyStaticFiles
.
Le code suivant met à jour WebRootFileProvider
, qui permet au Tag Helper d’image de fournir une version :
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();
Considérations de sécurité pour les fichiers statiques
Avertissement
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
etUseStaticFiles
sont soumises aux restrictions de respect de la casse et de caractères du système de fichiers sous-jacent. Par exemple, Windows ne respecte pas la casse, mais macOS et Linux la respectent.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 :
- Accédez à la fonctionnalité Modules.
- Sélectionnez StaticFileModule dans la liste.
- Cliquez sur Supprimer dans l’encadré Actions.
Avertissement
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 fichier web.config 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.
Délivrez des fichiers en dehors de wwwroot en mettant à jour IWebHostEnvironment.WebRootPath
Quand IWebHostEnvironment.WebRootPath est défini sur un dossier autre que wwwroot
:
- Dans l’environnement de développement, les ressources statiques trouvées dans
wwwroot
et dans la mise à jour deIWebHostEnvironment.WebRootPath
sont délivrées à partir dewwwroot
. - Dans tout environnement autre que celui de développement, les ressources statiques en double sont délivrées à partir du dossier
IWebHostEnvironment.WebRootPath
mis à jour.
Considérez une application web créée avec le modèle web vide :
Contenant un fichier
Index.html
danswwwroot
etwwwroot-custom
.Avec le fichier
Program.cs
mis à jour suivant qui définitWebRootPath = "wwwroot-custom"
:var builder = WebApplication.CreateBuilder(new WebApplicationOptions { Args = args, // Look for static files in "wwwroot-custom" WebRootPath = "wwwroot-custom" }); var app = builder.Build(); app.UseDefaultFiles(); app.UseStaticFiles(); app.Run();
Dans le code précédent, les demandes adressées à /
:
- Dans l’environnement de développement, retournent
wwwroot/Index.html
- Dans tout environnement autre que celui de développement, retournent
wwwroot-custom/Index.html
Pour vous assurer que les ressources à partir de wwwroot-custom
sont retournées, utilisez l’une des approches suivantes :
Supprimez les ressources nommées en double dans
wwwroot
.Définissez
"ASPNETCORE_ENVIRONMENT"
dansProperties/launchSettings.json
sur n’importe quelle valeur autre que"Development"
.Désactivez complètement les ressources web statiques en définissant
<StaticWebAssetsEnabled>false</StaticWebAssetsEnabled>
dans le fichier projet. AVERTISSEMENT, la désactivation des ressources web statiques désactive les bibliothèques de classes Razor.Ajoutez le code JSON suivant au fichier projet :
<ItemGroup> <Content Remove="wwwroot\**" /> </ItemGroup>
Le code suivant met à jour IWebHostEnvironment.WebRootPath
vers une valeur de non-développement, garantissant que le contenu en double est retourné à partir de wwwroot-custom
plutôt que wwwroot
:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Examine Hosting environment: logging value
EnvironmentName = Environments.Staging,
WebRootPath = "wwwroot-custom"
});
var app = builder.Build();
app.Logger.LogInformation("ASPNETCORE_ENVIRONMENT: {env}",
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));
app.Logger.LogInformation("app.Environment.IsDevelopment(): {env}",
app.Environment.IsDevelopment().ToString());
app.UseDefaultFiles();
app.UseStaticFiles();
app.Run();
Ressources supplémentaires
Par Rick Anderson et Kirk Larkin
Les fichiers statiques, comme les fichiers HTML, CSS, images et JavaScript, sont des ressources qu’une application ASP.NET Core délivre directement aux clients, par défaut.
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Délivrer des fichiers statiques
Les fichiers statiques sont stockés dans le répertoire racine web du projet. Le répertoire par défaut est {content root}/wwwroot
, mais il peut être modifié avec la méthode UseWebRoot. Pour plus d’informations, consultez Racine de contenu et Racine web.
La méthode CreateDefaultBuilder définit le répertoire actif comme racine du contenu :
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>();
});
}
Le code précédent a été créé avec le modèle d’application web.
Les fichiers statiques sont accessibles via un chemin relatif à la racine web. Par exemple, les modèles de projet Application web contiennent plusieurs dossiers dans le dossier wwwroot
:
wwwroot
css
js
lib
Envisagez de créer le dossier wwwroot/images et d’ajouter le fichier wwwroot/images/MyImage.jpg
. Le format URI pour accéder à un fichier dans le dossier images
est https://<hostname>/images/<image_file_name>
. Par exemple, https://localhost:5001/images/MyImage.jpg
Délivrer des fichiers à la racine web
Les modèles d’application web par défaut appellent la méthode UseStaticFiles dans Startup.Configure
, ce qui permet de délivrer les fichiers statiques :
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();
});
}
La surcharge de la méthode UseStaticFiles
sans paramètres marque les fichiers à la racine web comme étant délivrables. Le balisage suivant référence wwwroot/images/MyImage.jpg
:
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
Dans le code précédent, le caractère tilde ~/
pointe vers la racine web.
Délivrer des fichiers en dehors de la racine web
Considérez une hiérarchie de répertoires dans laquelle les fichiers statiques à délivrer se trouvent en dehors de la racine web :
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
Une demande peut accéder au fichier red-rose.jpg
en configurant l’intergiciel de fichiers statiques comme suit :
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();
});
}
Dans le code précédent, la hiérarchie de répertoires MyStaticFiles est exposée publiquement via le segment d’URI StaticFiles. Une demande à https://<hostname>/StaticFiles/images/red-rose.jpg
délivre le fichier red-rose.jpg
.
Le balisage suivant référence MyStaticFiles/images/red-rose.jpg
:
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
Définir des en-têtes de réponse HTTP
Un objet StaticFileOptions peut être utilisé pour définir des en-têtes de réponse HTTP. En plus de configurer la possibilité de délivrer des fichiers statiques à partir de la racine web, le code suivant définit l’en-tête Cache-Control
:
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();
});
}
Le code précédent définit l’âge maximal à 604800 secondes (7 jours).
Autorisations des fichiers statiques
Les modèles ASP.NET Core appellent 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 délivrés par l’intergiciel de fichiers statiques, tels que ceux sous
wwwroot
, sont accessibles publiquement.
Pour délivrer des fichiers statiques en fonction d’une autorisation :
- Stockez-les en dehors de
wwwroot
. - Appelez
UseStaticFiles
, en spécifiant un chemin, après avoir appeléUseAuthorization
. - Définissez la stratégie d’autorisation de secours.
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.
Dans le code précédent, la stratégie d’autorisation de secours exige que tous les utilisateurs soient authentifiés. Les points de terminaison tels que les contrôleurs, Razor Pages, etc., qui spécifient leurs propres exigences d’autorisation, n’utilisent pas la stratégie d’autorisation de secours. Par exemple, Razor Pages, 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 secours.
RequireAuthenticatedUser ajoute DenyAnonymousAuthorizationRequirement à l’instance actuelle, ce qui impose l’authentification de l’utilisateur actuel.
Les ressources statiques sous wwwroot
sont accessibles publiquement, car l’intergiciel de fichiers statiques par défaut (app.UseStaticFiles();
) est appelé avant UseAuthentication
. Les ressources statiques figurant dans le dossier MyStaticFiles nécessitent une authentification. Cet exemple de code illustre ceci.
Une autre approche pour traiter les fichiers en fonction de l’autorisation consiste à :
- Les stocker en dehors de
wwwroot
et de tout répertoire accessible à l’intergiciel de fichiers statiques. - Les délivrer via une méthode d’action à laquelle une autorisation est appliquée et à retourner un objet FileResult :
[Authorize]
public IActionResult BannerImage()
{
var filePath = Path.Combine(
_env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");
return PhysicalFile(filePath, "image/jpeg");
}
Exploration de répertoires
La navigation dans les répertoires permet de lister les 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 l’exploration des répertoires avec :
- AddDirectoryBrowser dans
Startup.ConfigureServices
. - UseDirectoryBrowser dans
Startup.Configure
.
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();
});
}
Le code précédent permet l’exploration des répertoires du dossier wwwroot/images en utilisant l’URL https://<hostname>/MyImages
, avec des liens vers chaque fichier et dossier :
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 délivrer 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 :
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
doit être appelé avant UseStaticFiles
pour délivrer le fichier par défaut. UseDefaultFiles
est un module de réécriture d’URL qui ne délivre pas le fichier.
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 mydefault.html
:
var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
Le code suivant montre Startup.Configure
avec le code précédent :
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 pour les documents par défaut
UseFileServer combine les fonctionnalités de UseStaticFiles
, de UseDefaultFiles
et éventuellement de UseDirectoryBrowser
.
Appelez app.UseFileServer
pour activer la possibilité de délivrer des fichiers statiques et le fichier par défaut. L’exploration des répertoires n’est pas activée. Le code suivant montre Startup.Configure
avec UseFileServer
:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseFileServer();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
Le code suivant active la possibilité de délivrer des fichiers statiques, le fichier par défaut et l’exploration des répertoires :
app.UseFileServer(enableDirectoryBrowsing: true);
Le code suivant montre Startup.Configure
avec le code précédent :
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();
});
}
Considérez la hiérarchie de répertoires suivante :
wwwroot
css
images
js
MyStaticFiles
images
MyImage.jpg
default.html
Le code suivant active la possibilité de délivrer des fichiers statiques, le fichier par défaut et l’exploration des répertoires de MyStaticFiles
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDirectoryBrowser();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles(); // For the wwwroot folder.
// using Microsoft.Extensions.FileProviders;
// using System.IO;
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles",
EnableDirectoryBrowsing = true
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
AddDirectoryBrowser doit être appelé quand la valeur de la propriété EnableDirectoryBrowsing
est true
.
En utilisant la hiérarchie de fichiers et le code précédent, les URL sont résolues comme suit :
URI | Response |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
MyStaticFiles/default.html |
Si aucun fichier nommé par défaut n’existe dans le répertoire MyStaticFiles, https://<hostname>/StaticFiles
retourne la liste des répertoires avec des liens interactifs :
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://<hostname>/StaticFiles
à https://<hostname>/StaticFiles/
. Les URL relatives au sein du répertoire StaticFiles ne sont pas valides sans barre oblique de fin (/
).
FileExtensionContentTypeProvider
La classe FileExtensionContentTypeProvider contient une propriété Mappings
qui agit comme un mappage des extensions de fichiers à des types de contenu MIME. Dans l’exemple suivant, plusieurs extensions de fichiers sont mappées à des types MIME connus. L’extension .rtf est remplacée et l’extension .mp4 est supprimée :
// 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"
});
Le code suivant montre Startup.Configure
avec le code précédent :
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();
});
}
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 délivrer des types inconnus et rend le fichier inconnu en tant qu’image :
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "image/png"
});
Le code suivant montre Startup.Configure
avec le code précédent :
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();
});
}
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.
Avertissement
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. FileExtensionContentTypeProvider fournit une alternative plus sûre pour délivrer des fichiers avec des extensions non standard.
Délivrer des fichiers à partir de plusieurs emplacements
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 ce problème GitHub.
Considérations de sécurité pour les fichiers statiques
Avertissement
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
etUseStaticFiles
sont soumises aux restrictions de respect de la casse et de caractères du système de fichiers sous-jacent. Par exemple, Windows ne respecte pas la casse, mais macOS et Linux la respectent.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 :
- Accédez à la fonctionnalité Modules.
- Sélectionnez StaticFileModule dans la liste.
- Cliquez sur Supprimer dans l’encadré Actions.
Avertissement
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 fichier web.config 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.