File statici in ASP.NET Core

Nota

Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 8 di questo articolo.

Avviso

Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere Criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 8 di questo articolo.

Importante

Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Per la versione corrente, vedere la versione .NET 8 di questo articolo.

Di Rick Anderson

I file statici, ad esempio HTML, CSS, immagini e JavaScript, sono asset di un'app ASP.NET Core serve direttamente ai client per impostazione predefinita.

Per Blazor indicazioni sui file statici, che aggiunge o sostituisce le linee guida in questo articolo, vedere ASP.NET File statici coreBlazor.

Usare i file statici

I file statici vengono archiviati all'interno della directory radice Web del progetto. La directory predefinita è {content root}/wwwroot, ma può essere modificata con il UseWebRoot metodo . Per altre informazioni, vedere Radice del contenuto e Radice Web.

Il metodo CreateBuilder imposta la radice del contenuto nella directory corrente:

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

I file statici sono accessibili tramite un percorso relativo alla radice Web. Ad esempio, i modelli di progetto applicazione Web contengono diverse cartelle all'interno della wwwroot cartella :

  • wwwroot
    • css
    • js
    • lib

Prendere in considerazione un'app con il wwwroot/images/MyImage.jpg file . Il formato URI per accedere a un file nella images cartella è https://<hostname>/images/<image_file_name>. Ad esempio, https://localhost:5001/images/MyImage.jpg

MapStaticAssets

La creazione di app Web con prestazioni elevate richiede l'ottimizzazione della distribuzione degli asset nel browser. Le possibili ottimizzazioni includono:

  • Servire un determinato asset una volta fino a quando il file non cambia o il browser cancella la cache. Impostare l'intestazione ETag .
  • Impedire al browser di usare asset obsoleti o non aggiornati dopo l'aggiornamento di un'app. Impostare l'intestazione Ultima modifica .
  • Configurare le intestazioni di memorizzazione nella cache appropriate.
  • Usare il middleware di memorizzazione nella cache.
  • Gestire le versioni compresse degli asset, quando possibile.
  • Usare una rete CDN per gestire gli asset più vicini all'utente.
  • Ridurre al minimo le dimensioni degli asset serviti al browser. Questa ottimizzazione non include la minificazione.

MapStaticAssets sono convenzioni degli endpoint di routing che ottimizzano la distribuzione di asset statici in un'app. È progettato per funzionare con tutti i framework dell'interfaccia utente, tra cui Blazor, Razor Pages e MVC.

UseStaticFiles gestisce anche i file statici, ma non fornisce lo stesso livello di ottimizzazione di MapStaticAssets. Per un confronto tra UseStaticFiles e , vedere Ottimizzazione della distribuzione di asset MapStaticAssetsWeb statici.

Gestire i file nella radice Web

I modelli di app Web predefiniti chiamano il MapStaticAssets metodo in Program.cs, che consente di gestire i file statici:

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

L'overload del metodo senza UseStaticFiles parametri contrassegna i file nella radice Web come serveble. I riferimenti di wwwroot/images/MyImage.jpgmarkup seguenti:

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

Nel markup precedente il carattere ~ tilde punta alla radice Web.

Usare i file all'esterno della radice Web

Si consideri una gerarchia di directory in cui i file statici da gestire si trovano all'esterno della radice Web:

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

Una richiesta può accedere al red-rose.jpg file configurando il middleware dei file statici come indicato di seguito:

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

Nel codice precedente la gerarchia di directory MyStaticFiles viene esposta pubblicamente tramite il segmento dell'URI StaticFiles. Richiesta di gestione https://<hostname>/StaticFiles/images/red-rose.jpg del red-rose.jpg file.

I riferimenti di MyStaticFiles/images/red-rose.jpgmarkup seguenti:

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

Per gestire i file da più posizioni, vedere Gestire i file da più posizioni.

Impostare le intestazioni della risposta HTTP

Un StaticFileOptions oggetto può essere usato per impostare le intestazioni di risposta HTTP. Oltre a configurare la gestione di file statici dalla radice Web, il codice seguente imposta l'intestazione 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();

Il codice precedente rende i file statici disponibili pubblicamente nella cache locale per una settimana.

Autorizzazione dei file statici

I modelli ASP.NET Core chiamano MapStaticAssets prima di chiamare UseAuthorization. La maggior parte delle app segue questo modello. Quando il middleware dei file statici viene chiamato prima del middleware di autorizzazione:

  • Non vengono eseguiti controlli di autorizzazione sui file statici.
  • I file statici gestiti dal middleware dei file statici, ad esempio quelli wwwrootin , sono accessibili pubblicamente.

Per gestire i file statici in base all'autorizzazione:

  • Archiviarli all'esterno di wwwroot.
  • Chiamare UseStaticFiles, specificando un percorso, dopo aver chiamato UseAuthorization.
  • Impostare i criteri di autorizzazione di fallback.
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();

Nel codice precedente, i criteri di autorizzazione di fallback richiedono l'autenticazione di tutti gli utenti. Gli endpoint, ad esempio controller, Razor pagine e così via, che specificano i propri requisiti di autorizzazione non usano i criteri di autorizzazione di fallback. Ad esempio, Razor Pages, controller o metodi di azione con [AllowAnonymous] o [Authorize(PolicyName="MyPolicy")] usano l'attributo di autorizzazione applicato anziché i criteri di autorizzazione di fallback.

RequireAuthenticatedUser aggiunge DenyAnonymousAuthorizationRequirement all'istanza corrente, che impone l'autenticazione dell'utente corrente.

Gli asset statici in wwwroot sono accessibili pubblicamente perché il middleware dei file statici predefinito (app.UseStaticFiles();) viene chiamato prima UseAuthenticationdi . Gli asset statici nella cartella MyStaticFiles richiedono l'autenticazione. Il codice di esempio illustra questa operazione.

Un approccio alternativo per gestire i file in base all'autorizzazione consiste nel:

  • Archiviarli all'esterno di wwwroot e qualsiasi directory accessibile al middleware dei file statici.

  • Gestirli tramite un metodo di azione a cui viene applicata l'autorizzazione e restituire un FileResult oggetto :

    [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'approccio precedente richiede una pagina o un endpoint per ogni file. Il codice seguente restituisce i file o carica i file per gli utenti autenticati:

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 nell'esempio precedente usa il buffer di memoria per il caricamento. Per la gestione dello streaming di file di grandi dimensioni. Vedere Caricare file di grandi dimensioni con lo streaming.

Per l'esempio completo, vedere la cartella GitHub StaticFileAuth .

Esplorazione directory

L'esplorazione della directory consente l'elenco di directory all'interno di directory specificate.

L'esplorazione della directory è disabilitata per impostazione predefinita per motivi di sicurezza. Per altre informazioni, vedere Considerazioni sulla sicurezza per i file statici.

Abilitare l'esplorazione della directory con AddDirectoryBrowser e 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();

Il codice precedente consente l'esplorazione della directory della cartella wwwroot/images usando l'URL https://<hostname>/MyImages, con collegamenti a ogni file e cartella:

esplorazione directory

AddDirectoryBrowseraggiunge i servizi richiesti dal middleware di esplorazione della directory, incluso HtmlEncoder. Questi servizi possono essere aggiunti da altre chiamate, ad esempio AddRazorPages, ma è consigliabile chiamare AddDirectoryBrowser per assicurarsi che i servizi vengano aggiunti in tutte le app.

Gestire i documenti predefiniti

L'impostazione di una pagina predefinita fornisce ai visitatori un punto di partenza in un sito. Per gestire un file predefinito da wwwroot senza richiedere all'URL della richiesta di includere il nome del file, chiamare il UseDefaultFiles metodo :

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 deve essere chiamato prima di UseStaticFiles per usare il file predefinito. UseDefaultFiles è un rewriter URL che non serve il file.

Con UseDefaultFiles, richiede a una cartella nella wwwroot ricerca:

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

Il primo file trovato dall'elenco viene fornito come se la richiesta includa il nome del file. L'URL del browser continua a riflettere l'URI richiesto. Nell'app di esempio, ad esempio, una richiesta da eseguire https://localhost:<port>/def/ default.html da wwwroot/def.

Il codice seguente modifica il nome file predefinito in 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 per i documenti predefiniti

UseFileServer combina le funzionalità di UseStaticFiles, UseDefaultFilese facoltativamente UseDirectoryBrowser.

Chiamare app.UseFileServer per abilitare la gestione di file statici e il file predefinito. L'esplorazione della directory non è abilitata:

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

Il codice seguente abilita la gestione di file statici, il file predefinito e l'esplorazione della directory:

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

Considerare la gerarchia di directory seguente:

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

Il codice seguente abilita la gestione di file statici, il file predefinito e l'esplorazione della directory di 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 deve essere chiamato quando il valore della EnableDirectoryBrowsing proprietà è true.

Usando la gerarchia di file e il codice precedenti, gli URL vengono risolti nel modo seguente:

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

Se nella directory MyStaticFiles non esiste alcun file denominato predefinito, https://<hostname>/StaticFiles restituisce l'elenco di directory con collegamenti selezionabili:

Elenco di file statici

UseDefaultFiles ed UseDirectoryBrowser eseguire un reindirizzamento lato client dall'URI di destinazione senza un finale / all'URI di destinazione con un oggetto finale /. Ad esempio, da https://<hostname>/StaticFiles a https://<hostname>/StaticFiles/. Gli URL relativi all'interno della directory StaticFiles non sono validi senza una barra finale (/) a meno che non venga usata l'opzione RedirectToAppendTrailingSlash di DefaultFilesOptions .

Classe FileExtensionContentTypeProvider

La FileExtensionContentTypeProvider classe contiene una proprietà Mappings che funge da mapping delle estensioni di file ai tipi di contenuto MIME. Nell'esempio seguente vengono mappate diverse estensioni di file ai tipi MIME noti. L'estensione .rtf viene sostituita e .mp4 viene rimossa:

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

Vedere Tipi di contenuto MIME.

Tipi di contenuto non standard

Il middleware dei file statici comprende quasi 400 tipi di contenuto di file noti. Se l'utente richiede un file con un tipo di file sconosciuto, il middleware del file statico passa la richiesta al middleware successivo nella pipeline. Se nessun middleware gestisce la richiesta, viene restituita la risposta 404 Non trovato. Se è abilitata l'esplorazione directory, viene visualizzato un collegamento al file nella visualizzazione directory.

Il codice seguente consente di usare tipi sconosciuti ed esegue il rendering del file sconosciuto come immagine:

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

Con il codice precedente, una richiesta per un file con un tipo di contenuto sconosciuto viene restituita come immagine.

Avviso

L'abilitazione ServeUnknownFileTypes è un rischio per la sicurezza. È disabilitato per impostazione predefinita e ne è sconsigliato l'uso. La classe FileExtensionContentTypeProvider offre un'alternativa più sicura per usare i file con estensioni non standard.

Gestire i file da più posizioni

Si consideri la pagina seguente Razor che visualizza il /MyStaticFiles/image3.png file:

@page

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

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

UseStaticFiles e UseFileServer per impostazione predefinita il provider di file che punta a wwwroot. Altre istanze di UseStaticFiles e UseFileServer possono essere fornite con altri provider di file per gestire i file da altre posizioni. L'esempio seguente chiama UseStaticFiles due volte per gestire i file da e wwwroot MyStaticFiles:

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

Uso del codice precedente:

  • Viene visualizzato il /MyStaticFiles/image3.png file.
  • Gli helper AppendVersion tag immagine non vengono applicati perché gli helper tag dipendono da WebRootFileProvider. WebRootFileProvider non è stato aggiornato per includere la MyStaticFiles cartella .

Il codice seguente aggiorna WebRootFileProvider, che consente all'helper tag image di fornire una versione:

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

Nota

L'approccio precedente si applica alle Razor app Pages e MVC. Per indicazioni applicabili a Blazor Web Apps, vedere ASP.NET File statici coreBlazor.

Considerazioni sulla sicurezza per i file statici

Avviso

UseDirectoryBrowser e UseStaticFiles possono perdere segreti. È consigliabile disabilitare l'esplorazione directory nell'ambiente di produzione. Controllare attentamente quali sono le directory abilitate tramite UseStaticFiles o UseDirectoryBrowser. L'intera directory e le relative sottodirectory diventano pubblicamente accessibili. Archiviare i file adatti per la gestione al pubblico in una directory dedicata, ad esempio <content_root>/wwwroot. Separare questi file dalle visualizzazioni MVC, Razor dalle pagine, dai file di configurazione e così via.

  • Gli URL per il contenuto esposto con UseDirectoryBrowser, UseStaticFilese sono soggetti alla distinzione tra maiuscole e minuscole MapStaticAssets e alle restrizioni dei caratteri del file system sottostante. Ad esempio, Windows non fa distinzione tra maiuscole e minuscole, ma macOS e Linux non lo sono.

  • Le app ASP.NET Core ospitate in IIS usano il modulo ASP.NET Core per inoltrare tutte le richieste all'app, incluse le richieste di file statici. Il gestore di file statici IIS non viene usato e non ha la possibilità di gestire le richieste.

  • Completare la procedura seguente in Gestione IIS per rimuovere il gestore di file statici di IIS a livello di server o di sito Web:

    1. Passare alla funzionalità Moduli.
    2. Selezionare StaticFileModule nell'elenco.
    3. Fare clic su Rimuovi nell'intestazione laterale Azioni.

Avviso

Se il gestore di file statici di IIS è abilitato e il modulo ASP.NET Core non è configurato correttamente, vengono usati i file statici. Tale scenario si verifica ad esempio se il file web.config non è stato distribuito.

  • Inserire i file di codice, inclusi .cs e .cshtml, all'esterno della radice Web del progetto dell'app. Si crea quindi un separazione logica tra il contenuto sul lato client dell'app e il codice basato su server. In questo modo si impedisce la perdita del codice sul lato server.

Gestire i file all'esterno di wwwroot aggiornando IWebHostEnvironment.WebRootPath

Quando IWebHostEnvironment.WebRootPath è impostato su una cartella diversa da wwwroot:

  • Nell'ambiente di sviluppo, gli asset statici presenti sia in wwwroot che nell'aggiornamento IWebHostEnvironment.WebRootPath vengono gestiti da wwwroot.
  • In qualsiasi ambiente diverso dallo sviluppo, gli asset statici duplicati vengono serviti dalla cartella aggiornata IWebHostEnvironment.WebRootPath .

Si consideri un'app Web creata con il modello Web vuoto:

  • Contenente un Index.html file in wwwroot e wwwroot-custom.

  • Con il file aggiornato Program.cs seguente che imposta WebRootPath = "wwwroot-custom":

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

Nel codice precedente, richiede a /:

  • Nell'ambiente di sviluppo restituire wwwroot/Index.html
  • In qualsiasi ambiente diverso dalla restituzione dello sviluppo wwwroot-custom/Index.html

Per assicurarsi che gli asset vengano wwwroot-custom restituiti, usare uno degli approcci seguenti:

  • Eliminare asset denominati duplicati in wwwroot.

  • Impostare "ASPNETCORE_ENVIRONMENT" in su Properties/launchSettings.json qualsiasi valore diverso da "Development".

  • Disabilitare completamente gli asset Web statici impostando <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled> nel file di progetto. AVVISO, disabilitando gli asset Web statici, le Razor librerie di classi vengono disabilitate.

  • Aggiungere il codice XML seguente al file di progetto:

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

Il codice seguente viene aggiornato IWebHostEnvironment.WebRootPath a un valore non di sviluppo, garantendo che venga restituito contenuto duplicato anziché wwwroot-custom 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();

Risorse aggiuntive

Di Rick Anderson

I file statici, ad esempio HTML, CSS, immagini e JavaScript, sono asset di un'app ASP.NET Core serve direttamente ai client per impostazione predefinita.

Usare i file statici

I file statici vengono archiviati all'interno della directory radice Web del progetto. La directory predefinita è {content root}/wwwroot, ma può essere modificata con il UseWebRoot metodo . Per altre informazioni, vedere Radice del contenuto e Radice Web.

Il metodo CreateBuilder imposta la radice del contenuto nella directory corrente:

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

I file statici sono accessibili tramite un percorso relativo alla radice Web. Ad esempio, i modelli di progetto applicazione Web contengono diverse cartelle all'interno della wwwroot cartella :

  • wwwroot
    • css
    • js
    • lib

È consigliabile creare la cartella wwwroot/images e aggiungere il wwwroot/images/MyImage.jpg file. Il formato URI per accedere a un file nella images cartella è https://<hostname>/images/<image_file_name>. Ad esempio, https://localhost:5001/images/MyImage.jpg

Gestire i file nella radice Web

I modelli di app Web predefiniti chiamano il UseStaticFiles metodo in Program.cs, che consente di gestire i file statici:

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

L'overload del metodo senza UseStaticFiles parametri contrassegna i file nella radice Web come serveble. I riferimenti di wwwroot/images/MyImage.jpgmarkup seguenti:

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

Nel markup precedente il carattere ~ tilde punta alla radice Web.

Usare i file all'esterno della radice Web

Si consideri una gerarchia di directory in cui i file statici da gestire si trovano all'esterno della radice Web:

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

Una richiesta può accedere al red-rose.jpg file configurando il middleware dei file statici come indicato di seguito:

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

Nel codice precedente la gerarchia di directory MyStaticFiles viene esposta pubblicamente tramite il segmento dell'URI StaticFiles. Richiesta di gestione https://<hostname>/StaticFiles/images/red-rose.jpg del red-rose.jpg file.

I riferimenti di MyStaticFiles/images/red-rose.jpgmarkup seguenti:

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

Per gestire i file da più posizioni, vedere Gestire i file da più posizioni.

Impostare le intestazioni della risposta HTTP

Un StaticFileOptions oggetto può essere usato per impostare le intestazioni di risposta HTTP. Oltre a configurare la gestione di file statici dalla radice Web, il codice seguente imposta l'intestazione 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();

Il codice precedente rende i file statici disponibili pubblicamente nella cache locale per una settimana (604800 secondi).

Autorizzazione dei file statici

I modelli ASP.NET Core chiamano UseStaticFiles prima di chiamare UseAuthorization. La maggior parte delle app segue questo modello. Quando il middleware dei file statici viene chiamato prima del middleware di autorizzazione:

  • Non vengono eseguiti controlli di autorizzazione sui file statici.
  • I file statici gestiti dal middleware dei file statici, ad esempio quelli wwwrootin , sono accessibili pubblicamente.

Per gestire i file statici in base all'autorizzazione:

  • Archiviarli all'esterno di wwwroot.
  • Chiamare UseStaticFiles, specificando un percorso, dopo aver chiamato UseAuthorization.
  • Impostare i criteri di autorizzazione di fallback.
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();

Nel codice precedente, i criteri di autorizzazione di fallback richiedono l'autenticazione di tutti gli utenti. Gli endpoint, ad esempio controller, Razor pagine e così via, che specificano i propri requisiti di autorizzazione non usano i criteri di autorizzazione di fallback. Ad esempio, Razor Pages, controller o metodi di azione con [AllowAnonymous] o [Authorize(PolicyName="MyPolicy")] usano l'attributo di autorizzazione applicato anziché i criteri di autorizzazione di fallback.

RequireAuthenticatedUser aggiunge DenyAnonymousAuthorizationRequirement all'istanza corrente, che impone l'autenticazione dell'utente corrente.

Gli asset statici in wwwroot sono accessibili pubblicamente perché il middleware dei file statici predefinito (app.UseStaticFiles();) viene chiamato prima UseAuthenticationdi . Gli asset statici nella cartella MyStaticFiles richiedono l'autenticazione. Il codice di esempio illustra questa operazione.

Un approccio alternativo per gestire i file in base all'autorizzazione consiste nel:

  • Archiviarli all'esterno di wwwroot e qualsiasi directory accessibile al middleware dei file statici.

  • Gestirli tramite un metodo di azione a cui viene applicata l'autorizzazione e restituire un FileResult oggetto :

    [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'approccio precedente richiede una pagina o un endpoint per ogni file. Il codice seguente restituisce i file o carica i file per gli utenti autenticati:

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://video2.skills-academy.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();

Per l'esempio completo, vedere la cartella GitHub StaticFileAuth .

Esplorazione directory

L'esplorazione della directory consente l'elenco di directory all'interno di directory specificate.

L'esplorazione della directory è disabilitata per impostazione predefinita per motivi di sicurezza. Per altre informazioni, vedere Considerazioni sulla sicurezza per i file statici.

Abilitare l'esplorazione della directory con AddDirectoryBrowser e 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();

Il codice precedente consente l'esplorazione della directory della cartella wwwroot/images usando l'URL https://<hostname>/MyImages, con collegamenti a ogni file e cartella:

esplorazione directory

AddDirectoryBrowseraggiunge i servizi richiesti dal middleware di esplorazione della directory, incluso HtmlEncoder. Questi servizi possono essere aggiunti da altre chiamate, ad esempio AddRazorPages, ma è consigliabile chiamare AddDirectoryBrowser per assicurarsi che i servizi vengano aggiunti in tutte le app.

Gestire i documenti predefiniti

L'impostazione di una pagina predefinita fornisce ai visitatori un punto di partenza in un sito. Per gestire un file predefinito da wwwroot senza richiedere all'URL della richiesta di includere il nome del file, chiamare il UseDefaultFiles metodo :

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 deve essere chiamato prima di UseStaticFiles per usare il file predefinito. UseDefaultFiles è un rewriter URL che non serve il file.

Con UseDefaultFiles, richiede a una cartella nella wwwroot ricerca:

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

Il primo file trovato dall'elenco viene fornito come se la richiesta includa il nome del file. L'URL del browser continua a riflettere l'URI richiesto.

Il codice seguente modifica il nome file predefinito in 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 per i documenti predefiniti

UseFileServer combina le funzionalità di UseStaticFiles, UseDefaultFilese facoltativamente UseDirectoryBrowser.

Chiamare app.UseFileServer per abilitare la gestione di file statici e il file predefinito. L'esplorazione della directory non è abilitata:

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

Il codice seguente abilita la gestione di file statici, il file predefinito e l'esplorazione della directory:

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

Considerare la gerarchia di directory seguente:

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

Il codice seguente abilita la gestione di file statici, il file predefinito e l'esplorazione della directory di 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 deve essere chiamato quando il valore della EnableDirectoryBrowsing proprietà è true.

Usando la gerarchia di file e il codice precedenti, gli URL vengono risolti nel modo seguente:

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

Se nella directory MyStaticFiles non esiste alcun file denominato predefinito, https://<hostname>/StaticFiles restituisce l'elenco di directory con collegamenti selezionabili:

Elenco di file statici

UseDefaultFiles ed UseDirectoryBrowser eseguire un reindirizzamento lato client dall'URI di destinazione senza un finale / all'URI di destinazione con un oggetto finale /. Ad esempio, da https://<hostname>/StaticFiles a https://<hostname>/StaticFiles/. Gli URL relativi all'interno della directory StaticFiles non sono validi senza una barra finale (/) a meno che non venga usata l'opzione RedirectToAppendTrailingSlash di DefaultFilesOptions .

Classe FileExtensionContentTypeProvider

La FileExtensionContentTypeProvider classe contiene una Mappings proprietà che funge da mapping delle estensioni di file ai tipi di contenuto MIME. Nell'esempio seguente vengono mappate diverse estensioni di file ai tipi MIME noti. L'estensione .rtf viene sostituita e .mp4 viene rimossa:

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

Vedere Tipi di contenuto MIME.

Tipi di contenuto non standard

Il middleware dei file statici comprende quasi 400 tipi di contenuto di file noti. Se l'utente richiede un file con un tipo di file sconosciuto, il middleware del file statico passa la richiesta al middleware successivo nella pipeline. Se nessun middleware gestisce la richiesta, viene restituita la risposta 404 Non trovato. Se è abilitata l'esplorazione directory, viene visualizzato un collegamento al file nella visualizzazione directory.

Il codice seguente consente di usare tipi sconosciuti ed esegue il rendering del file sconosciuto come immagine:

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

Con il codice precedente, una richiesta per un file con un tipo di contenuto sconosciuto viene restituita come immagine.

Avviso

L'abilitazione ServeUnknownFileTypes è un rischio per la sicurezza. È disabilitato per impostazione predefinita e ne è sconsigliato l'uso. La classe FileExtensionContentTypeProvider offre un'alternativa più sicura per usare i file con estensioni non standard.

Gestire i file da più posizioni

Si consideri la pagina seguente Razor che visualizza il /MyStaticFiles/image3.png file:

@page

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

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

UseStaticFiles e UseFileServer per impostazione predefinita il provider di file che punta a wwwroot. Altre istanze di UseStaticFiles e UseFileServer possono essere fornite con altri provider di file per gestire i file da altre posizioni. L'esempio seguente chiama UseStaticFiles due volte per gestire i file da e wwwroot MyStaticFiles:

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

Uso del codice precedente:

  • Viene visualizzato il /MyStaticFiles/image3.png file.
  • Gli helper AppendVersion tag immagine non vengono applicati perché gli helper tag dipendono da WebRootFileProvider. WebRootFileProvider non è stato aggiornato per includere la MyStaticFiles cartella .

Il codice seguente aggiorna WebRootFileProvider, che consente all'helper tag image di fornire una versione:

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

Nota

L'approccio precedente si applica alle Razor app Pages e MVC. Per indicazioni applicabili a Blazor Web Apps, vedere ASP.NET File statici coreBlazor.

Considerazioni sulla sicurezza per i file statici

Avviso

L'uso di UseDirectoryBrowser e UseStaticFiles può comportare la perdita di informazioni riservate. È consigliabile disabilitare l'esplorazione directory nell'ambiente di produzione. Controllare attentamente quali sono le directory abilitate tramite UseStaticFiles o UseDirectoryBrowser. L'intera directory e le relative sottodirectory diventano pubblicamente accessibili. Archiviare i file adatti per la gestione al pubblico in una directory dedicata, ad esempio <content_root>/wwwroot. Separare questi file dalle visualizzazioni MVC, Razor dalle pagine, dai file di configurazione e così via.

  • Gli URL per il contenuto esposto con UseDirectoryBrowser e UseStaticFiles sono soggetti a distinzione tra maiuscole e minuscole e a limitazione di caratteri del file system sottostante. Ad esempio, Windows non fa distinzione tra maiuscole e minuscole, ma macOS e Linux non lo sono.

  • Le app ASP.NET Core ospitate in IIS usano il modulo ASP.NET Core per inoltrare tutte le richieste all'app, incluse le richieste di file statici. Il gestore di file statici IIS non viene usato e non ha la possibilità di gestire le richieste.

  • Completare la procedura seguente in Gestione IIS per rimuovere il gestore di file statici di IIS a livello di server o di sito Web:

    1. Passare alla funzionalità Moduli.
    2. Selezionare StaticFileModule nell'elenco.
    3. Fare clic su Rimuovi nell'intestazione laterale Azioni.

Avviso

Se il gestore di file statici di IIS è abilitato e il modulo ASP.NET Core non è configurato correttamente, vengono usati i file statici. Tale scenario si verifica ad esempio se il file web.config non è stato distribuito.

  • Inserire i file di codice, inclusi .cs e .cshtml, all'esterno della radice Web del progetto dell'app. Si crea quindi un separazione logica tra il contenuto sul lato client dell'app e il codice basato su server. In questo modo si impedisce la perdita del codice sul lato server.

Gestire i file all'esterno di wwwroot aggiornando IWebHostEnvironment.WebRootPath

Quando IWebHostEnvironment.WebRootPath è impostato su una cartella diversa da wwwroot:

  • Nell'ambiente di sviluppo, gli asset statici presenti sia in wwwroot che nell'aggiornamento IWebHostEnvironment.WebRootPath vengono gestiti da wwwroot.
  • In qualsiasi ambiente diverso dallo sviluppo, gli asset statici duplicati vengono serviti dalla cartella aggiornata IWebHostEnvironment.WebRootPath .

Si consideri un'app Web creata con il modello Web vuoto:

  • Contenente un Index.html file in wwwroot e wwwroot-custom.

  • Con il file aggiornato Program.cs seguente che imposta WebRootPath = "wwwroot-custom":

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

Nel codice precedente, richiede a /:

  • Nell'ambiente di sviluppo restituire wwwroot/Index.html
  • In qualsiasi ambiente diverso dalla restituzione dello sviluppo wwwroot-custom/Index.html

Per assicurarsi che gli asset vengano wwwroot-custom restituiti, usare uno degli approcci seguenti:

  • Eliminare asset denominati duplicati in wwwroot.

  • Impostare "ASPNETCORE_ENVIRONMENT" in su Properties/launchSettings.json qualsiasi valore diverso da "Development".

  • Disabilitare completamente gli asset Web statici impostando <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled> nel file di progetto. AVVISO, disabilitando gli asset Web statici, le Razor librerie di classi vengono disabilitate.

  • Aggiungere il codice JSON seguente al file di progetto:

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

Il codice seguente viene aggiornato IWebHostEnvironment.WebRootPath a un valore non di sviluppo, garantendo che venga restituito contenuto duplicato anziché wwwroot-custom 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();

Risorse aggiuntive

Di Rick Anderson e Kirk Larkin

I file statici, ad esempio HTML, CSS, immagini e JavaScript, sono asset di un'app ASP.NET Core serve direttamente ai client per impostazione predefinita.

Usare i file statici

I file statici vengono archiviati all'interno della directory radice Web del progetto. La directory predefinita è {content root}/wwwroot, ma può essere modificata con il UseWebRoot metodo . Per altre informazioni, vedere Radice del contenuto e Radice Web.

Il metodo CreateBuilder imposta la radice del contenuto nella directory corrente:

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

I file statici sono accessibili tramite un percorso relativo alla radice Web. Ad esempio, i modelli di progetto applicazione Web contengono diverse cartelle all'interno della wwwroot cartella :

  • wwwroot
    • css
    • js
    • lib

È consigliabile creare la cartella wwwroot/images e aggiungere il wwwroot/images/MyImage.jpg file. Il formato URI per accedere a un file nella images cartella è https://<hostname>/images/<image_file_name>. Ad esempio, https://localhost:5001/images/MyImage.jpg

Gestire i file nella radice Web

I modelli di app Web predefiniti chiamano il UseStaticFiles metodo in Program.cs, che consente di gestire i file statici:

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

L'overload del metodo senza UseStaticFiles parametri contrassegna i file nella radice Web come serveble. I riferimenti di wwwroot/images/MyImage.jpgmarkup seguenti:

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

Nel markup precedente il carattere ~ tilde punta alla radice Web.

Usare i file all'esterno della radice Web

Si consideri una gerarchia di directory in cui i file statici da gestire si trovano all'esterno della radice Web:

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

Una richiesta può accedere al red-rose.jpg file configurando il middleware dei file statici come indicato di seguito:

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

Nel codice precedente la gerarchia di directory MyStaticFiles viene esposta pubblicamente tramite il segmento dell'URI StaticFiles. Richiesta di gestione https://<hostname>/StaticFiles/images/red-rose.jpg del red-rose.jpg file.

I riferimenti di MyStaticFiles/images/red-rose.jpgmarkup seguenti:

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

Per gestire i file da più posizioni, vedere Gestire i file da più posizioni.

Impostare le intestazioni della risposta HTTP

Un StaticFileOptions oggetto può essere usato per impostare le intestazioni di risposta HTTP. Oltre a configurare la gestione di file statici dalla radice Web, il codice seguente imposta l'intestazione 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();

Il codice precedente rende i file statici disponibili pubblicamente nella cache locale per una settimana (604800 secondi).

Autorizzazione dei file statici

I modelli ASP.NET Core chiamano UseStaticFiles prima di chiamare UseAuthorization. La maggior parte delle app segue questo modello. Quando il middleware dei file statici viene chiamato prima del middleware di autorizzazione:

  • Non vengono eseguiti controlli di autorizzazione sui file statici.
  • I file statici gestiti dal middleware dei file statici, ad esempio quelli wwwrootin , sono accessibili pubblicamente.

Per gestire i file statici in base all'autorizzazione:

  • Archiviarli all'esterno di wwwroot.
  • Chiamare UseStaticFiles, specificando un percorso, dopo aver chiamato UseAuthorization.
  • Impostare i criteri di autorizzazione di fallback.
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();

Nel codice precedente, i criteri di autorizzazione di fallback richiedono l'autenticazione di tutti gli utenti. Gli endpoint, ad esempio controller, Razor pagine e così via, che specificano i propri requisiti di autorizzazione non usano i criteri di autorizzazione di fallback. Ad esempio, Razor Pages, controller o metodi di azione con [AllowAnonymous] o [Authorize(PolicyName="MyPolicy")] usano l'attributo di autorizzazione applicato anziché i criteri di autorizzazione di fallback.

RequireAuthenticatedUser aggiunge DenyAnonymousAuthorizationRequirement all'istanza corrente, che impone l'autenticazione dell'utente corrente.

Gli asset statici in wwwroot sono accessibili pubblicamente perché il middleware dei file statici predefinito (app.UseStaticFiles();) viene chiamato prima UseAuthenticationdi . Gli asset statici nella cartella MyStaticFiles richiedono l'autenticazione. Il codice di esempio illustra questa operazione.

Un approccio alternativo per gestire i file in base all'autorizzazione consiste nel:

  • Archiviarli all'esterno di wwwroot e qualsiasi directory accessibile al middleware dei file statici.
  • Gestirli tramite un metodo di azione a cui viene applicata l'autorizzazione e restituire un FileResult oggetto :
[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");
    }
}

Esplorazione directory

L'esplorazione della directory consente l'elenco di directory all'interno di directory specificate.

L'esplorazione della directory è disabilitata per impostazione predefinita per motivi di sicurezza. Per altre informazioni, vedere Considerazioni sulla sicurezza per i file statici.

Abilitare l'esplorazione della directory con AddDirectoryBrowser e 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();

Il codice precedente consente l'esplorazione della directory della cartella wwwroot/images usando l'URL https://<hostname>/MyImages, con collegamenti a ogni file e cartella:

esplorazione directory

AddDirectoryBrowseraggiunge i servizi richiesti dal middleware di esplorazione della directory, incluso HtmlEncoder. Questi servizi possono essere aggiunti da altre chiamate, ad esempio AddRazorPages, ma è consigliabile chiamare AddDirectoryBrowser per assicurarsi che i servizi vengano aggiunti in tutte le app.

Gestire i documenti predefiniti

L'impostazione di una pagina predefinita fornisce ai visitatori un punto di partenza in un sito. Per gestire un file predefinito da wwwroot senza richiedere all'URL della richiesta di includere il nome del file, chiamare il UseDefaultFiles metodo :

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 deve essere chiamato prima di UseStaticFiles per usare il file predefinito. UseDefaultFiles è un rewriter URL che non serve il file.

Con UseDefaultFiles, richiede a una cartella nella wwwroot ricerca:

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

Il primo file trovato dall'elenco viene fornito come se la richiesta includa il nome del file. L'URL del browser continua a riflettere l'URI richiesto.

Il codice seguente modifica il nome file predefinito in 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 per i documenti predefiniti

UseFileServer combina le funzionalità di UseStaticFiles, UseDefaultFilese facoltativamente UseDirectoryBrowser.

Chiamare app.UseFileServer per abilitare la gestione di file statici e il file predefinito. L'esplorazione della directory non è abilitata:

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

Il codice seguente abilita la gestione di file statici, il file predefinito e l'esplorazione della directory:

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

Considerare la gerarchia di directory seguente:

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

Il codice seguente abilita la gestione di file statici, il file predefinito e l'esplorazione della directory di 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 deve essere chiamato quando il valore della EnableDirectoryBrowsing proprietà è true.

Usando la gerarchia di file e il codice precedenti, gli URL vengono risolti nel modo seguente:

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

Se nella directory MyStaticFiles non esiste alcun file denominato predefinito, https://<hostname>/StaticFiles restituisce l'elenco di directory con collegamenti selezionabili:

Elenco di file statici

UseDefaultFiles ed UseDirectoryBrowser eseguire un reindirizzamento lato client dall'URI di destinazione senza un finale / all'URI di destinazione con un oggetto finale /. Ad esempio, da https://<hostname>/StaticFiles a https://<hostname>/StaticFiles/. Gli URL relativi all'interno della directory StaticFiles non sono validi senza una barra finale (/) a meno che non venga usata l'opzione RedirectToAppendTrailingSlash di DefaultFilesOptions .

Classe FileExtensionContentTypeProvider

La FileExtensionContentTypeProvider classe contiene una Mappings proprietà che funge da mapping delle estensioni di file ai tipi di contenuto MIME. Nell'esempio seguente vengono mappate diverse estensioni di file ai tipi MIME noti. L'estensione .rtf viene sostituita e .mp4 viene rimossa:

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

Vedere Tipi di contenuto MIME.

Tipi di contenuto non standard

Il middleware dei file statici comprende quasi 400 tipi di contenuto di file noti. Se l'utente richiede un file con un tipo di file sconosciuto, il middleware del file statico passa la richiesta al middleware successivo nella pipeline. Se nessun middleware gestisce la richiesta, viene restituita la risposta 404 Non trovato. Se è abilitata l'esplorazione directory, viene visualizzato un collegamento al file nella visualizzazione directory.

Il codice seguente consente di usare tipi sconosciuti ed esegue il rendering del file sconosciuto come immagine:

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

Con il codice precedente, una richiesta per un file con un tipo di contenuto sconosciuto viene restituita come immagine.

Avviso

L'abilitazione ServeUnknownFileTypes è un rischio per la sicurezza. È disabilitato per impostazione predefinita e ne è sconsigliato l'uso. La classe FileExtensionContentTypeProvider offre un'alternativa più sicura per usare i file con estensioni non standard.

Gestire i file da più posizioni

Si consideri la pagina seguente Razor che visualizza il /MyStaticFiles/image3.png file:

@page

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

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

UseStaticFiles e UseFileServer per impostazione predefinita il provider di file che punta a wwwroot. Altre istanze di UseStaticFiles e UseFileServer possono essere fornite con altri provider di file per gestire i file da altre posizioni. L'esempio seguente chiama UseStaticFiles due volte per gestire i file da e wwwroot MyStaticFiles:

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

Uso del codice precedente:

  • Viene visualizzato il /MyStaticFiles/image3.png file.
  • Gli helper AppendVersion tag immagine non vengono applicati perché gli helper tag dipendono da WebRootFileProvider. WebRootFileProvider non è stato aggiornato per includere la MyStaticFiles cartella .

Il codice seguente aggiorna WebRootFileProvider, che consente all'helper tag image di fornire una versione:

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

Considerazioni sulla sicurezza per i file statici

Avviso

L'uso di UseDirectoryBrowser e UseStaticFiles può comportare la perdita di informazioni riservate. È consigliabile disabilitare l'esplorazione directory nell'ambiente di produzione. Controllare attentamente quali sono le directory abilitate tramite UseStaticFiles o UseDirectoryBrowser. L'intera directory e le relative sottodirectory diventano pubblicamente accessibili. Archiviare i file adatti per la gestione al pubblico in una directory dedicata, ad esempio <content_root>/wwwroot. Separare questi file dalle visualizzazioni MVC, Razor dalle pagine, dai file di configurazione e così via.

  • Gli URL per il contenuto esposto con UseDirectoryBrowser e UseStaticFiles sono soggetti a distinzione tra maiuscole e minuscole e a limitazione di caratteri del file system sottostante. Ad esempio, Windows non fa distinzione tra maiuscole e minuscole, ma macOS e Linux non lo sono.

  • Le app ASP.NET Core ospitate in IIS usano il modulo ASP.NET Core per inoltrare tutte le richieste all'app, incluse le richieste di file statici. Il gestore di file statici IIS non viene usato e non ha la possibilità di gestire le richieste.

  • Completare la procedura seguente in Gestione IIS per rimuovere il gestore di file statici di IIS a livello di server o di sito Web:

    1. Passare alla funzionalità Moduli.
    2. Selezionare StaticFileModule nell'elenco.
    3. Fare clic su Rimuovi nell'intestazione laterale Azioni.

Avviso

Se il gestore di file statici di IIS è abilitato e il modulo ASP.NET Core non è configurato correttamente, vengono usati i file statici. Tale scenario si verifica ad esempio se il file web.config non è stato distribuito.

  • Inserire i file di codice, inclusi .cs e .cshtml, all'esterno della radice Web del progetto dell'app. Si crea quindi un separazione logica tra il contenuto sul lato client dell'app e il codice basato su server. In questo modo si impedisce la perdita del codice sul lato server.

Gestire i file all'esterno di wwwroot aggiornando IWebHostEnvironment.WebRootPath

Quando IWebHostEnvironment.WebRootPath è impostato su una cartella diversa da wwwroot:

  • Nell'ambiente di sviluppo, gli asset statici presenti sia in wwwroot che nell'aggiornamento IWebHostEnvironment.WebRootPath vengono gestiti da wwwroot.
  • In qualsiasi ambiente diverso dallo sviluppo, gli asset statici duplicati vengono serviti dalla cartella aggiornata IWebHostEnvironment.WebRootPath .

Si consideri un'app Web creata con il modello Web vuoto:

  • Contenente un Index.html file in wwwroot e wwwroot-custom.

  • Con il file aggiornato Program.cs seguente che imposta WebRootPath = "wwwroot-custom":

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

Nel codice precedente, richiede a /:

  • Nell'ambiente di sviluppo restituire wwwroot/Index.html
  • In qualsiasi ambiente diverso dalla restituzione dello sviluppo wwwroot-custom/Index.html

Per assicurarsi che gli asset vengano wwwroot-custom restituiti, usare uno degli approcci seguenti:

  • Eliminare asset denominati duplicati in wwwroot.

  • Impostare "ASPNETCORE_ENVIRONMENT" in su Properties/launchSettings.json qualsiasi valore diverso da "Development".

  • Disabilitare completamente gli asset Web statici impostando <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled> nel file di progetto. AVVISO, disabilitando gli asset Web statici, le Razor librerie di classi vengono disabilitate.

  • Aggiungere il codice JSON seguente al file di progetto:

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

Il codice seguente viene aggiornato IWebHostEnvironment.WebRootPath a un valore non di sviluppo, garantendo che venga restituito contenuto duplicato anziché wwwroot-custom 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();

Risorse aggiuntive

Di Rick Anderson e Kirk Larkin

I file statici, ad esempio HTML, CSS, immagini e JavaScript, sono asset di un'app ASP.NET Core serve direttamente ai client per impostazione predefinita.

Visualizzare o scaricare il codice di esempio (procedura per il download)

Usare i file statici

I file statici vengono archiviati all'interno della directory radice Web del progetto. La directory predefinita è {content root}/wwwroot, ma può essere modificata con il UseWebRoot metodo . Per altre informazioni, vedere Radice del contenuto e Radice Web.

Il metodo CreateDefaultBuilder imposta la radice del contenuto nella directory corrente:

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

Il codice precedente è stato creato con il modello di app Web.

I file statici sono accessibili tramite un percorso relativo alla radice Web. Ad esempio, i modelli di progetto applicazione Web contengono diverse cartelle all'interno della wwwroot cartella :

  • wwwroot
    • css
    • js
    • lib

È consigliabile creare la cartella wwwroot/images e aggiungere il wwwroot/images/MyImage.jpg file. Il formato URI per accedere a un file nella images cartella è https://<hostname>/images/<image_file_name>. Ad esempio, https://localhost:5001/images/MyImage.jpg

Gestire i file nella radice Web

I modelli di app Web predefiniti chiamano il UseStaticFiles metodo in Startup.Configure, che consente di gestire i file statici:

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

L'overload del metodo senza UseStaticFiles parametri contrassegna i file nella radice Web come serveble. I riferimenti di wwwroot/images/MyImage.jpgmarkup seguenti:

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

Nel codice precedente il carattere ~/ tilde punta alla radice Web.

Usare i file all'esterno della radice Web

Si consideri una gerarchia di directory in cui i file statici da gestire si trovano all'esterno della radice Web:

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

Una richiesta può accedere al red-rose.jpg file configurando il middleware dei file statici come indicato di seguito:

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

Nel codice precedente la gerarchia di directory MyStaticFiles viene esposta pubblicamente tramite il segmento dell'URI StaticFiles. Richiesta di gestione https://<hostname>/StaticFiles/images/red-rose.jpg del red-rose.jpg file.

I riferimenti di MyStaticFiles/images/red-rose.jpgmarkup seguenti:

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

Impostare le intestazioni della risposta HTTP

Un StaticFileOptions oggetto può essere usato per impostare le intestazioni di risposta HTTP. Oltre a configurare la gestione di file statici dalla radice Web, il codice seguente imposta l'intestazione 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();
    });
}

Il codice precedente imposta max-age su 604800 secondi (7 giorni).

Sono state aggiunte le intestazioni della risposta che visualizzano l'intestazione Cache-Control

Autorizzazione dei file statici

I modelli ASP.NET Core chiamano UseStaticFiles prima di chiamare UseAuthorization. La maggior parte delle app segue questo modello. Quando il middleware dei file statici viene chiamato prima del middleware di autorizzazione:

  • Non vengono eseguiti controlli di autorizzazione sui file statici.
  • I file statici gestiti dal middleware dei file statici, ad esempio quelli wwwrootin , sono accessibili pubblicamente.

Per gestire i file statici in base all'autorizzazione:

  • Archiviarli all'esterno di wwwroot.
  • Chiamare UseStaticFiles, specificando un percorso, dopo aver chiamato UseAuthorization.
  • Impostare i criteri di autorizzazione di fallback.
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.

Nel codice precedente, i criteri di autorizzazione di fallback richiedono l'autenticazione di tutti gli utenti. Gli endpoint, ad esempio controller, Razor pagine e così via, che specificano i propri requisiti di autorizzazione non usano i criteri di autorizzazione di fallback. Ad esempio, Razor Pages, controller o metodi di azione con [AllowAnonymous] o [Authorize(PolicyName="MyPolicy")] usano l'attributo di autorizzazione applicato anziché i criteri di autorizzazione di fallback.

RequireAuthenticatedUser aggiunge DenyAnonymousAuthorizationRequirement all'istanza corrente, che impone l'autenticazione dell'utente corrente.

Gli asset statici in wwwroot sono accessibili pubblicamente perché il middleware dei file statici predefinito (app.UseStaticFiles();) viene chiamato prima UseAuthenticationdi . Gli asset statici nella cartella MyStaticFiles richiedono l'autenticazione. Il codice di esempio illustra questa operazione.

Un approccio alternativo per gestire i file in base all'autorizzazione consiste nel:

  • Archiviarli all'esterno di wwwroot e qualsiasi directory accessibile al middleware dei file statici.
  • Gestirli tramite un metodo di azione a cui viene applicata l'autorizzazione e restituire un FileResult oggetto :
[Authorize]
public IActionResult BannerImage()
{
    var filePath = Path.Combine(
        _env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");

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

Esplorazione directory

L'esplorazione della directory consente l'elenco di directory all'interno di directory specificate.

L'esplorazione della directory è disabilitata per impostazione predefinita per motivi di sicurezza. Per altre informazioni, vedere Considerazioni sulla sicurezza per i file statici.

Abilitare l'esplorazione della directory con:

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

Il codice precedente consente l'esplorazione della directory della cartella wwwroot/images usando l'URL https://<hostname>/MyImages, con collegamenti a ogni file e cartella:

esplorazione directory

Gestire i documenti predefiniti

L'impostazione di una pagina predefinita fornisce ai visitatori un punto di partenza in un sito. Per gestire un file predefinito da wwwroot senza richiedere all'URL della richiesta di includere il nome del file, chiamare il UseDefaultFiles metodo :

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 deve essere chiamato prima di UseStaticFiles per usare il file predefinito. UseDefaultFiles è un rewriter URL che non serve il file.

Con UseDefaultFiles, richiede a una cartella nella wwwroot ricerca:

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

Il primo file trovato dall'elenco viene fornito come se la richiesta includa il nome del file. L'URL del browser continua a riflettere l'URI richiesto.

Il codice seguente modifica il nome file predefinito in mydefault.html:

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

Il codice seguente mostra Startup.Configure con il codice precedente:

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 per i documenti predefiniti

UseFileServer combina le funzionalità di UseStaticFiles, UseDefaultFilese facoltativamente UseDirectoryBrowser.

Chiamare app.UseFileServer per abilitare la gestione di file statici e il file predefinito. L'esplorazione directory non è abilitata. Il codice seguente mostra Startup.Configure con 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();
    });
}

Il codice seguente abilita la gestione di file statici, il file predefinito e l'esplorazione della directory:

app.UseFileServer(enableDirectoryBrowsing: true);

Il codice seguente mostra Startup.Configure con il codice precedente:

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

Considerare la gerarchia di directory seguente:

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

Il codice seguente abilita la gestione di file statici, il file predefinito e l'esplorazione della directory di 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 deve essere chiamato quando il valore della EnableDirectoryBrowsing proprietà è true.

Dall'uso della gerarchia di file e del codice precedente ne deriva quanto segue:

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

Se nella directory MyStaticFiles non esiste alcun file denominato predefinito, https://<hostname>/StaticFiles restituisce l'elenco di directory con collegamenti selezionabili:

Elenco di file statici

UseDefaultFiles ed UseDirectoryBrowser eseguire un reindirizzamento lato client dall'URI di destinazione senza un finale / all'URI di destinazione con un oggetto finale /. Ad esempio, da https://<hostname>/StaticFiles a https://<hostname>/StaticFiles/. Gli URL relativi all'interno della directory StaticFiles non sono validi senza una barra finale (/).

Classe FileExtensionContentTypeProvider

La FileExtensionContentTypeProvider classe contiene una Mappings proprietà che funge da mapping delle estensioni di file ai tipi di contenuto MIME. Nell'esempio seguente vengono mappate diverse estensioni di file ai tipi MIME noti. L'estensione .rtf viene sostituita e .mp4 viene rimossa:

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

Il codice seguente mostra Startup.Configure con il codice precedente:

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

Vedere Tipi di contenuto MIME.

Tipi di contenuto non standard

Il middleware dei file statici comprende quasi 400 tipi di contenuto di file noti. Se l'utente richiede un file con un tipo di file sconosciuto, il middleware del file statico passa la richiesta al middleware successivo nella pipeline. Se nessun middleware gestisce la richiesta, viene restituita la risposta 404 Non trovato. Se è abilitata l'esplorazione directory, viene visualizzato un collegamento al file nella visualizzazione directory.

Il codice seguente consente di usare tipi sconosciuti ed esegue il rendering del file sconosciuto come immagine:

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

Il codice seguente mostra Startup.Configure con il codice precedente:

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

Con il codice precedente, una richiesta per un file con un tipo di contenuto sconosciuto viene restituita come immagine.

Avviso

L'abilitazione ServeUnknownFileTypes è un rischio per la sicurezza. È disabilitato per impostazione predefinita e ne è sconsigliato l'uso. La classe FileExtensionContentTypeProvider offre un'alternativa più sicura per usare i file con estensioni non standard.

Gestire i file da più posizioni

UseStaticFiles e UseFileServer per impostazione predefinita il provider di file che punta a wwwroot. Altre istanze di UseStaticFiles e UseFileServer possono essere fornite con altri provider di file per gestire i file da altre posizioni. Per altre informazioni, vedere questo problema in GitHub.

Considerazioni sulla sicurezza per i file statici

Avviso

L'uso di UseDirectoryBrowser e UseStaticFiles può comportare la perdita di informazioni riservate. È consigliabile disabilitare l'esplorazione directory nell'ambiente di produzione. Controllare attentamente quali sono le directory abilitate tramite UseStaticFiles o UseDirectoryBrowser. L'intera directory e le relative sottodirectory diventano pubblicamente accessibili. Archiviare i file adatti per la gestione al pubblico in una directory dedicata, ad esempio <content_root>/wwwroot. Separare questi file dalle visualizzazioni MVC, Razor dalle pagine, dai file di configurazione e così via.

  • Gli URL per il contenuto esposto con UseDirectoryBrowser e UseStaticFiles sono soggetti a distinzione tra maiuscole e minuscole e a limitazione di caratteri del file system sottostante. Ad esempio, Windows non fa distinzione tra maiuscole e minuscole, ma macOS e Linux non lo sono.

  • Le app ASP.NET Core ospitate in IIS usano il modulo ASP.NET Core per inoltrare tutte le richieste all'app, incluse le richieste di file statici. Il gestore di file statici IIS non viene usato e non ha la possibilità di gestire le richieste.

  • Completare la procedura seguente in Gestione IIS per rimuovere il gestore di file statici di IIS a livello di server o di sito Web:

    1. Passare alla funzionalità Moduli.
    2. Selezionare StaticFileModule nell'elenco.
    3. Fare clic su Rimuovi nell'intestazione laterale Azioni.

Avviso

Se il gestore di file statici di IIS è abilitato e il modulo ASP.NET Core non è configurato correttamente, vengono usati i file statici. Tale scenario si verifica ad esempio se il file web.config non è stato distribuito.

  • Inserire i file di codice, inclusi .cs e .cshtml, all'esterno della radice Web del progetto dell'app. Si crea quindi un separazione logica tra il contenuto sul lato client dell'app e il codice basato su server. In questo modo si impedisce la perdita del codice sul lato server.

Risorse aggiuntive