Bagikan melalui


File statik di ASP.NET Core

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Peringatan

Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Penting

Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.

Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Oleh Rick Anderson

File statis, seperti HTML, CSS, gambar, dan JavaScript, adalah aset aplikasi ASP.NET Core berfungsi langsung ke klien secara default.

Menyajikan file statis

File statis disimpan dalam direktori akar web proyek. Direktori default adalah {content root}/wwwroot, tetapi dapat diubah dengan UseWebRoot metode . Untuk informasi selengkapnya, lihat Akar Konten dan Akar Web.

Metode CreateBuilder ini mengatur akar konten ke direktori saat ini:

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

File statis dapat diakses melalui jalur yang relatif terhadap akar web. Misalnya, templat proyek Aplikasi Web berisi beberapa folder dalam wwwroot folder:

  • wwwroot
    • css
    • js
    • lib

Pertimbangkan untuk membuat folder wwwroot/images dan menambahkan wwwroot/images/MyImage.jpg file. Format URI untuk mengakses file di images folder adalah https://<hostname>/images/<image_file_name>. Misalnya: https://localhost:5001/images/MyImage.jpg

Menyajikan file di direktori akar web

Templat aplikasi web default memanggil UseStaticFiles metode di Program.cs, yang memungkinkan file statis dilayani:

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

Metode overload tanpa parameter UseStaticFiles menandai file di root web sebagai dapat disajikan. Markup berikut merujuk ke wwwroot/images/MyImage.jpg:

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

Dalam markup sebelumnya, karakter tilde ~ mengarah ke root web.

Menyajikan file di luar akar web

Pertimbangkan hierarki direktori tempat file statis untuk dilayani berada di luar akar web:

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

Permintaan dapat mengakses berkas red-rose.jpg dengan mengonfigurasi Static File Middleware sebagai berikut:

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

Dalam kode sebelumnya, hierarki direktori MyStaticFiles diekspos secara publik melalui segmen URI StaticFiles . Permintaan untuk https://<hostname>/StaticFiles/images/red-rose.jpg menyajikan berkas red-rose.jpg.

Referensi markup berikut ini MyStaticFiles/images/red-rose.jpg:

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

Untuk menyajikan file dari beberapa lokasi, lihat Menyajikan file dari beberapa lokasi.

Mengatur header respons HTTP

Objek StaticFileOptions dapat digunakan untuk mengatur header respons HTTP. Selain mengonfigurasi penyajian file statis dari root web, kode berikut mengatur header 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();

Kode sebelumnya membuat file statis tersedia untuk umum di cache lokal selama satu minggu (604800 detik).

Otorisasi file statis

Templat ASP.NET Core memanggil UseStaticFiles sebelum memanggil UseAuthorization. Sebagian besar aplikasi mengikuti pola ini. Ketika Middleware File Statis dipanggil sebelum middleware otorisasi:

  • Tidak ada pemeriksaan otorisasi yang dilakukan pada file statis.
  • File statis yang dilayani oleh Middleware File Statis, seperti file di bawah wwwroot, dapat diakses secara publik.

Untuk menyajikan file statis berdasarkan otorisasi:

  • Simpan mereka di luar wwwroot.
  • Panggil UseStaticFiles, menentukan jalur, setelah memanggil UseAuthorization.
  • Atur kebijakan otorisasi 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();

Dalam kode sebelumnya, kebijakan otorisasi fallback mengharuskan semua pengguna diautentikasi. Titik akhir seperti pengontrol, Razor Halaman, dll yang menentukan persyaratan otorisasi mereka sendiri tidak menggunakan kebijakan otorisasi fallback. Misalnya, Razor Halaman, pengontrol, atau metode tindakan dengan [AllowAnonymous] atau [Authorize(PolicyName="MyPolicy")] menggunakan atribut otorisasi yang diterapkan daripada kebijakan otorisasi fallback.

RequireAuthenticatedUser menambahkan DenyAnonymousAuthorizationRequirement ke instans saat ini, yang memastikan bahwa pengguna saat ini telah diautentikasi.

Aset statis di bawah wwwroot dapat diakses secara publik karena Middleware File Statis default (app.UseStaticFiles();) dipanggil sebelum UseAuthentication. Aset statis di folder MyStaticFiles memerlukan autentikasi. Kode sampel menunjukkan ini.

Pendekatan alternatif untuk melayani file berdasarkan otorisasi adalah dengan:

  • Simpan elemen-elemen tersebut di luar wwwroot dan direktori apa pun yang dapat diakses oleh Middleware File Statis.

  • Sajikan melalui metode tindakan tempat otorisasi diterapkan dan mengembalikan FileResult objek:

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

Pendekatan sebelumnya memerlukan halaman atau titik akhir untuk setiap file. Kode berikut mengembalikan file atau mengunggah file untuk pengguna terautentikasi:

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

        if (File.Exists(filePath))
        {
            return TypedResults.PhysicalFile(filePath, fileDownloadName: $"{fileName}");
        }

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

// IFormFile uses memory buffer for uploading. For handling large file use streaming instead.
// https://learn.microsoft.com/aspnet/core/mvc/models/file-uploads#upload-large-files-with-streaming
app.MapPost("/files", async (IFormFile file, LinkGenerator linker, HttpContext context) =>
    {
        // Don't rely on the file.FileName as it is only metadata that can be manipulated by the end-user
        // Take a look at the `Utilities.IsFileValid` method that takes an IFormFile and validates its signature within the AllowedFileSignatures
        
        var fileSaveName = Guid.NewGuid().ToString("N") + Path.GetExtension(file.FileName);
        await SaveFileWithCustomFileName(file, fileSaveName);
        
        context.Response.Headers.Append("Location", linker.GetPathByName(context, "GetFileByName", new { fileName = fileSaveName}));
        return TypedResults.Ok("File Uploaded Successfully!");
    })
    .RequireAuthorization("AdminsOnly");

app.Run();

Lihat folder StaticFileAuth GitHub untuk sampel lengkapnya.

Penjelajahan direktori

Penjelajahan direktori memungkinkan daftar direktori dalam direktori tertentu.

Penjelajahan direktori dinonaktifkan secara default karena alasan keamanan. Untuk informasi selengkapnya, lihat Pertimbangan keamanan untuk file statis.

Aktifkan penjelajahan direktori dengan AddDirectoryBrowser dan 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();

Kode sebelumnya memungkinkan penjelajahan direktori folder wwwroot/images menggunakan URL https://<hostname>/MyImages, dengan tautan ke setiap file dan folder:

penjelajahan direktori

AddDirectoryBrowser menambahkan layanan yang diperlukan oleh middleware penjelajahan direktori, termasuk HtmlEncoder. Layanan ini dapat ditambahkan oleh panggilan lain, seperti AddRazorPages, tetapi sebaiknya panggil AddDirectoryBrowser untuk memastikan layanan ditambahkan di semua aplikasi.

Menyediakan dokumen default

Mengatur halaman default memberi pengunjung titik awal di situs. Untuk melayani file default dari wwwroot tanpa memerlukan URL permintaan untuk menyertakan nama file, panggil UseDefaultFiles metode :

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 harus dipanggil sebelumnya UseStaticFiles untuk melayani file default. UseDefaultFiles adalah penulis ulang URL yang tidak melayani file.

Dengan UseDefaultFiles, permintaan ke folder di wwwroot mencari:

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

File pertama yang ditemukan dari daftar dilayani seolah-olah permintaan menyertakan nama file. URL browser terus mencerminkan URI yang diminta.

Kode berikut mengubah nama file default menjadi 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();

Menggunakan UseFileServer untuk dokumen bawaan

UseFileServer menggabungkan fungsionalitas UseStaticFiles, UseDefaultFiles, dan secara UseDirectoryBrowseropsional .

Panggil app.UseFileServer untuk mengaktifkan penyajian file statis dan file default. Penjelajahan direktori tidak diaktifkan:

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

Kode berikut memungkinkan penyajian file statis, file default, dan penjelajahan direktori:

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

Pertimbangkan hierarki direktori berikut:

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

Kode berikut memungkinkan penyajian file statis, file default, dan penjelajahan direktori dari 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 harus dipanggil ketika EnableDirectoryBrowsing nilai properti adalah true.

Menggunakan hierarki dan kode file sebelumnya, URL diselesaikan sebagai berikut:

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

Jika tidak ada file dengan nama 'default' yang ada di direktori MyStaticFiles, https://<hostname>/StaticFiles akan mengembalikan daftar direktori dengan tautan yang dapat diklik.

Daftar file statis

UseDefaultFiles dan UseDirectoryBrowser melakukan pengalihan sisi klien dari URI target tanpa diakhiri / ke URI target yang diakhiri /. Misalnya, dari https://<hostname>/StaticFiles ke https://<hostname>/StaticFiles/. URL relatif dalam direktori StaticFiles tidak valid tanpa garis miring penutup (/) kecuali opsi DefaultFilesOptionsRedirectToAppendTrailingSlash digunakan.

FileExtensionContentTypeProvider

Kelas FileExtensionContentTypeProvider berisi Mappings properti yang berfungsi sebagai pemetaan ekstensi file ke jenis konten MIME. Dalam sampel berikut, beberapa ekstensi file dipetakan ke jenis MIME yang diketahui. Ekstensi .rtf diganti, dan .mp4 dihapus:

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

Lihat Jenis konten MIME.

Jenis konten non-standar

Middleware File Statis memahami hampir 400 jenis konten file yang diketahui. Jika pengguna meminta file dengan jenis file yang tidak diketahui, Middleware File Statis meneruskan permintaan ke middleware berikutnya dalam alur. Jika tidak ada middleware yang menangani permintaan, respons 404 Tidak Ditemukan dikembalikan. Jika penjelajahan direktori diaktifkan, tautan ke file ditampilkan dalam daftar direktori.

Kode berikut memungkinkan penyajian jenis yang tidak diketahui dan merender file yang tidak diketahui sebagai gambar:

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

Dengan kode sebelumnya, permintaan untuk file dengan jenis konten yang tidak diketahui dikembalikan sebagai gambar.

Peringatan

Mengaktifkan ServeUnknownFileTypes adalah risiko keamanan. Ini dinonaktifkan secara default, dan penggunaannya tidak disarankan. FileExtensionContentTypeProvider menyediakan alternatif yang lebih aman untuk melayani file dengan ekstensi non-standar.

Menyajikan file dari beberapa lokasi

Pertimbangkan halaman berikut Razor yang menampilkan /MyStaticFiles/image3.png file:

@page

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

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

UseStaticFiles dan UseFileServer secara default ke penyedia file yang mengarah ke wwwroot. Instans tambahan dari UseStaticFiles dan UseFileServer dapat disediakan dengan penyedia file lain untuk menyajikan file dari lokasi lain. Contoh berikut memanggil UseStaticFiles dua kali untuk menyajikan file dari wwwroot dan MyStaticFiles:

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

Menggunakan kode sebelumnya:

  • File /MyStaticFiles/image3.png ditampilkan.
  • Pembantu Tag ImageAppendVersion tidak diterapkan karena Pembantu Tag bergantung pada WebRootFileProvider. WebRootFileProvider belum diperbarui untuk menyertakan MyStaticFiles folder.

Kode berikut memperbarui WebRootFileProvider, yang memungkinkan Pembantu Tag Gambar untuk menyediakan versi:

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

Catatan

Pendekatan sebelumnya berlaku untuk Razor aplikasi Pages dan MVC. Untuk panduan yang berlaku untuk Blazor Web Apps, lihat ASP.NET Core Blazor static files.

Pertimbangan keamanan untuk file statis

Peringatan

UseDirectoryBrowser dan UseStaticFiles dapat membocorkan rahasia. Menonaktifkan penjelajahan direktori dalam produksi sangat disarankan. Tinjau direktori mana yang diaktifkan dengan hati-hati melalui UseStaticFiles atau UseDirectoryBrowser. Seluruh direktori dan sub-direktorinya dapat diakses secara publik. Simpan file yang cocok untuk dilayani ke publik di direktori khusus, seperti <content_root>/wwwroot. Pisahkan file-file ini dari tampilan MVC, Razor Halaman, file konfigurasi, dll.

  • URL untuk konten yang diekspos dengan UseDirectoryBrowser dan UseStaticFiles tunduk pada sensitivitas kasus dan pembatasan karakter dari sistem file yang mendasar. Misalnya, Windows tidak peka huruf besar/kecil, tetapi macOS dan Linux tidak.

  • Aplikasi ASP.NET Core yang dihosting di IIS menggunakan Modul ASP.NET Core untuk meneruskan semua permintaan ke aplikasi, termasuk permintaan untuk file statis. Handler file statis IIS tidak digunakan dan tidak memiliki kesempatan untuk menangani permintaan.

  • Selesaikan langkah-langkah berikut di Manajer IIS untuk menghapus handler file statis IIS di tingkat server atau situs web:

    1. Navigasi ke fitur Modul .
    2. Pilih StaticFileModule dalam daftar.
    3. Klik Hapus di bilah samping Tindakan .

Peringatan

Jika handler file statis IIS diaktifkan dan ASP.NET Core Module dikonfigurasi dengan salah, file statis akan disajikan. Ini terjadi, misalnya, jika file web.config tidak disebarkan.

  • Tempatkan file kode, termasuk .cs dan .cshtml, di luar akar web proyek aplikasi. Oleh karena itu, pemisahan logis dibuat antara konten sisi klien aplikasi dan kode berbasis server. Ini mencegah kode sisi server bocor.

Melayani file di luar wwwroot dengan memperbarui IWebHostEnvironment.WebRootPath

Kapan IWebHostEnvironment.WebRootPath diatur ke folder selain wwwroot:

  • Di lingkungan pengembangan, aset statis yang ditemukan di wwwroot dan di IWebHostEnvironment.WebRootPath yang telah diperbarui diproses dari wwwroot.
  • Di lingkungan apa pun selain pengembangan, aset statis duplikat disajikan dari folder yang diperbarui IWebHostEnvironment.WebRootPath .

Pertimbangkan aplikasi web yang dibuat dengan templat web kosong:

  • Berisi Index.html file di wwwroot dan wwwroot-custom.

  • Dengan file yang diperbarui Program.cs berikut yang menetapkan 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();
    

Dalam kode sebelumnya, permintaan ke /:

  • Pada lingkungan pengembangan, kembalikan wwwroot/Index.html
  • Di lingkungan apa pun selain pengembalian pengembangan wwwroot-custom/Index.html

Untuk memastikan aset dari wwwroot-custom dikembalikan, gunakan salah satu pendekatan berikut:

  • Hapus aset yang bernama sama di wwwroot.

  • Atur "ASPNETCORE_ENVIRONMENT" ke nilai apa pun selain Properties/launchSettings.json."Development"

  • Nonaktifkan aset web statis sepenuhnya dengan mengatur <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled> dalam file proyek. PERINGATAN, menonaktifkan aset web statis akan menonaktifkan Razor Pustaka Kelas.

  • Tambahkan JSON berikut ke file proyek:

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

Kode berikut diperbarui IWebHostEnvironment.WebRootPath ke nilai non pengembangan, menjamin konten duplikat dikembalikan dari wwwroot-custom bukan 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();

Sumber Daya Tambahan:

Oleh Rick Anderson dan Kirk Larkin

File statis, seperti HTML, CSS, gambar, dan JavaScript, adalah aset aplikasi ASP.NET Core berfungsi langsung ke klien secara default.

Layani file statis

File statis disimpan dalam direktori akar web proyek. Direktori default adalah {content root}/wwwroot, tetapi dapat diubah dengan UseWebRoot metode . Untuk informasi selengkapnya, lihat Akar Konten dan Akar Web.

Metode CreateBuilder ini mengatur akar konten ke direktori saat ini:

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

File statis dapat diakses melalui jalur yang relatif terhadap akar web. Misalnya, templat proyek Aplikasi Web berisi beberapa folder dalam wwwroot folder:

  • wwwroot
    • css
    • js
    • lib

Pertimbangkan untuk membuat folder wwwroot/images dan menambahkan wwwroot/images/MyImage.jpg file. Format URI untuk mengakses file di images folder adalah https://<hostname>/images/<image_file_name>. Misalnya: https://localhost:5001/images/MyImage.jpg

Melayani file di direktori root web

Templat aplikasi web default memanggil UseStaticFiles metode di Program.cs, yang memungkinkan file statis dilayani:

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

Metode overload tanpa parameter UseStaticFiles menandai file di root web sebagai dapat dihidangkan. Markup berikut mengacu pada wwwroot/images/MyImage.jpg:

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

Dalam markup sebelumnya, karakter ~ tilde menunjuk ke direktori root web.

Menyajikan file di luar akar web

Pertimbangkan hierarki direktori tempat file statis untuk dilayani berada di luar akar web:

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

Permintaan dapat mengakses berkas red-rose.jpg dengan mengonfigurasi Middleware File Statis sebagai berikut:

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

Dalam kode sebelumnya, hierarki direktori MyStaticFiles diekspos secara publik melalui segmen URI StaticFiles . Permintaan ke https://<hostname>/StaticFiles/images/red-rose.jpg menyediakan file red-rose.jpg.

Berikut referensi penandaan MyStaticFiles/images/red-rose.jpg:

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

Untuk menyajikan file dari beberapa lokasi, lihat Menyajikan file dari beberapa lokasi.

Mengatur header respons HTTP

Objek StaticFileOptions dapat digunakan untuk mengatur header respons HTTP. Selain mengonfigurasi penyajian file statis dari root web, kode berikut mengatur tajuk 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();

Kode sebelumnya membuat file statis tersedia untuk umum di cache lokal selama satu minggu (604800 detik).

Otorisasi file statis

Templat ASP.NET Core memanggil UseStaticFiles sebelum memanggil UseAuthorization. Sebagian besar aplikasi mengikuti pola ini. Ketika Middleware File Statis dipanggil sebelum middleware otorisasi:

  • Tidak ada pemeriksaan otorisasi yang dilakukan pada file statis.
  • File statis yang dilayani oleh Middleware File Statis, seperti file di bawah wwwroot, dapat diakses secara publik.

Untuk menyajikan file statis berdasarkan otorisasi:

  • Simpan di luar wwwroot.
  • Panggil UseStaticFiles, menentukan jalur, setelah memanggil UseAuthorization.
  • Atur kebijakan otorisasi 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();

Dalam kode sebelumnya, kebijakan otorisasi fallback mengharuskan semua pengguna diautentikasi. Titik akhir seperti pengontrol, Razor Halaman, dll yang menentukan persyaratan otorisasi mereka sendiri tidak menggunakan kebijakan otorisasi fallback. Misalnya, Razor Halaman, pengontrol, atau metode tindakan dengan [AllowAnonymous] atau [Authorize(PolicyName="MyPolicy")] menggunakan atribut otorisasi yang diterapkan daripada kebijakan otorisasi fallback.

RequireAuthenticatedUser menambahkan DenyAnonymousAuthorizationRequirement ke instans saat ini, yang memastikan bahwa pengguna saat ini telah diautentikasi.

Aset statis di bawah wwwroot dapat diakses secara publik karena Middleware File Statis default (app.UseStaticFiles();) dipanggil sebelum UseAuthentication. Aset statis di folder MyStaticFiles memerlukan autentikasi. Kode sampel menunjukkan ini.

Pendekatan alternatif untuk melayani file berdasarkan otorisasi adalah dengan:

  • Simpan di luar wwwroot dan direktori apa pun yang dapat diakses oleh Middleware File Statis.
  • Lakukan penyajian melalui metode aksi yang menerapkan otorisasi dan mengembalikan objek FileResult.
[Authorize]
public class BannerImageModel : PageModel
{
    private readonly IWebHostEnvironment _env;

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

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

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

Penjelajahan direktori

Penjelajahan direktori memungkinkan daftar direktori dalam direktori tertentu.

Penjelajahan direktori dinonaktifkan secara default karena alasan keamanan. Untuk informasi selengkapnya, lihat Pertimbangan keamanan untuk file statis.

Aktifkan penjelajahan direktori dengan AddDirectoryBrowser dan 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();

Kode sebelumnya memungkinkan penjelajahan direktori folder wwwroot/images menggunakan URL https://<hostname>/MyImages, dengan tautan ke setiap file dan folder:

penjelajahan direktori

AddDirectoryBrowser menambahkan layanan yang diperlukan oleh middleware penjelajahan direktori, termasuk HtmlEncoder. Layanan ini dapat ditambahkan oleh panggilan lain, seperti AddRazorPages, tetapi sebaiknya panggil AddDirectoryBrowser untuk memastikan layanan ditambahkan di semua aplikasi.

Menyediakan dokumen standar

Mengatur halaman default memberi pengunjung titik awal di situs. Untuk melayani file default dari wwwroot tanpa memerlukan URL permintaan untuk menyertakan nama file, panggil UseDefaultFiles metode :

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 harus dipanggil sebelumnya UseStaticFiles untuk melayani file default. UseDefaultFiles adalah penulis ulang URL yang tidak melayani file.

Dengan UseDefaultFiles, permintaan ke folder di wwwroot mencari:

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

File pertama yang ditemukan dari daftar dilayani seolah-olah permintaan menyertakan nama file. URL browser terus mencerminkan URI yang diminta.

Kode berikut mengubah nama file default menjadi 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 untuk dokumen default

UseFileServer menggabungkan fungsionalitas UseStaticFiles, UseDefaultFiles, dan secara UseDirectoryBrowseropsional .

Panggil app.UseFileServer untuk mengaktifkan penyajian file statis dan file default. Penjelajahan direktori tidak diaktifkan:

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

Kode berikut memungkinkan penyajian file statis, file default, dan penjelajahan direktori:

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

Pertimbangkan hierarki direktori berikut:

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

Kode berikut memungkinkan penyajian file statis, file default, dan penjelajahan direktori dari 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 harus dipanggil ketika EnableDirectoryBrowsing nilai properti adalah true.

Menggunakan hierarki dan kode file sebelumnya, URL diselesaikan sebagai berikut:

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

Jika tidak ada file bernama default di direktori MyStaticFiles, https://<hostname>/StaticFiles akan menampilkan daftar direktori dengan tautan yang dapat diklik.

Daftar file statis

UseDefaultFiles dan UseDirectoryBrowser melakukan pengalihan sisi klien dari URI target tanpa trailing / ke URI target dengan trailing /. Misalnya, dari https://<hostname>/StaticFiles ke https://<hostname>/StaticFiles/. URL relatif dalam direktori StaticFiles tidak valid tanpa garis miring di akhir (/) kecuali opsi DefaultFilesOptions dari RedirectToAppendTrailingSlash digunakan.

FileExtensionContentTypeProvider

Kelas FileExtensionContentTypeProvider berisi Mappings properti yang berfungsi sebagai pemetaan ekstensi file ke jenis konten MIME. Dalam sampel berikut, beberapa ekstensi file dipetakan ke jenis MIME yang diketahui. Ekstensi .rtf diganti, dan .mp4 dihapus:

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

Lihat Jenis konten MIME.

Jenis konten non-standar

Middleware File Statis memahami hampir 400 jenis konten file yang diketahui. Jika pengguna meminta file dengan jenis file yang tidak diketahui, Middleware File Statis meneruskan permintaan ke middleware berikutnya dalam alur. Jika tidak ada middleware yang menangani permintaan, respons 404 Tidak Ditemukan dikembalikan. Jika penjelajahan direktori diaktifkan, tautan ke file ditampilkan dalam daftar direktori.

Kode berikut memungkinkan penyajian jenis yang tidak diketahui dan merender file yang tidak diketahui sebagai gambar:

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

Dengan kode sebelumnya, permintaan untuk file dengan jenis konten yang tidak diketahui dikembalikan sebagai gambar.

Peringatan

Mengaktifkan ServeUnknownFileTypes adalah risiko keamanan. Ini dinonaktifkan secara default, dan penggunaannya tidak disarankan. FileExtensionContentTypeProvider menyediakan alternatif yang lebih aman untuk melayani file dengan ekstensi non-standar.

Menyajikan file dari beberapa lokasi

Pertimbangkan halaman berikut Razor yang menampilkan /MyStaticFiles/image3.png file:

@page

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

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

UseStaticFiles dan UseFileServer default ke penyedia file yang mengarah ke wwwroot. Instans tambahan dari UseStaticFiles dan UseFileServer dapat disediakan dengan penyedia file lain untuk menyediakan file dari lokasi lain. Contoh berikut memanggil UseStaticFiles dua kali untuk melayani file dari kedua wwwroot dan MyStaticFiles:

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

Menggunakan kode sebelumnya:

  • File /MyStaticFiles/image3.png ditampilkan.
  • Pembantu Tag Gambar tidak diterapkan karena Pembantu Tag bergantung pada WebRootFileProvider. WebRootFileProvider belum diperbarui untuk menyertakan MyStaticFiles folder.

Kode berikut memperbarui WebRootFileProvider, yang memungkinkan Pembantu Tag Gambar untuk menyediakan versi:

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

Pertimbangan keamanan untuk file statis

Peringatan

UseDirectoryBrowser dan UseStaticFiles dapat membocorkan rahasia. Menonaktifkan penjelajahan direktori dalam produksi sangat disarankan. Tinjau direktori mana yang diaktifkan dengan hati-hati melalui UseStaticFiles atau UseDirectoryBrowser. Seluruh direktori dan sub-direktorinya dapat diakses secara publik. Simpan file yang cocok untuk dilayani ke publik di direktori khusus, seperti <content_root>/wwwroot. Pisahkan file-file ini dari tampilan MVC, Razor Halaman, file konfigurasi, dll.

  • URL untuk konten yang diekspos dengan UseDirectoryBrowser dan UseStaticFiles tunduk pada sensitivitas kasus dan pembatasan karakter dari sistem file yang mendasar. Misalnya, Windows tidak peka huruf besar/kecil, tetapi macOS dan Linux tidak.

  • Aplikasi ASP.NET Core yang di-hosting di IIS menggunakan Modul ASP.NET Core untuk meneruskan semua permintaan ke aplikasi, termasuk permintaan untuk file statis. Handler file statis IIS tidak digunakan dan tidak memiliki kesempatan untuk menangani permintaan.

  • Selesaikan langkah-langkah berikut di Manajer IIS untuk menghapus handler file statis IIS di tingkat server atau situs web:

    1. Arahkan ke fitur Modul.
    2. Pilih StaticFileModule dalam daftar.
    3. Klik Hapus di bilah tindakan di samping.

Peringatan

Jika handler file statis IIS diaktifkan dan ASP.NET Core Module dikonfigurasi dengan salah, file statis dilayani. Ini terjadi, misalnya, jika file web.config tidak disebarkan.

  • Tempatkan file kode, termasuk .cs dan .cshtml, di luar akar web proyek aplikasi. Oleh karena itu, pemisahan logis dibuat antara konten sisi klien aplikasi dan kode berbasis server. Ini mencegah kode sisi server bocor.

Melayani file di luar wwwroot dengan memperbarui IWebHostEnvironment.WebRootPath

Kapan IWebHostEnvironment.WebRootPath diatur ke folder selain wwwroot:

  • Di lingkungan pengembangan, aset statis yang terdapat pada wwwroot dan IWebHostEnvironment.WebRootPath yang telah diperbarui disajikan dari wwwroot.
  • Di lingkungan apa pun selain pengembangan, aset statis duplikat disajikan dari folder yang diperbarui IWebHostEnvironment.WebRootPath .

Pertimbangkan aplikasi web yang dibuat dengan templat web kosong:

  • Mengandung sebuah Index.html file di wwwroot dan wwwroot-custom.

  • Dengan file yang diperbarui Program.cs berikut yang menetapkan 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();
    

Dalam kode sebelumnya, permintaan ke /:

  • Kembali ke lingkungan pengembangan wwwroot/Index.html
  • Di lingkungan apa pun selain pengembalian pengembangan wwwroot-custom/Index.html

Untuk memastikan aset dari wwwroot-custom dikembalikan, gunakan salah satu pendekatan berikut:

  • Hapus aset dengan nama duplikat di wwwroot.

  • Atur "ASPNETCORE_ENVIRONMENT" ke nilai apa pun selain Properties/launchSettings.json."Development"

  • Nonaktifkan aset web statis sepenuhnya dengan mengatur <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled> dalam file proyek. PERINGATAN, menonaktifkan aset web statis akan menyebabkan Pustaka Kelas dinonaktifkan.

  • Tambahkan JSON berikut ke file proyek:

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

Kode berikut diperbarui IWebHostEnvironment.WebRootPath ke nilai non pengembangan, menjamin konten duplikat dikembalikan dari wwwroot-custom bukan 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();

Sumber Daya Tambahan:

Oleh Rick Anderson dan Kirk Larkin

File statis, seperti HTML, CSS, gambar, dan JavaScript, adalah aset aplikasi ASP.NET Core berfungsi langsung ke klien secara default.

Melihat atau mengunduh kode sampel (cara mengunduh)

Menyajikan berkas statis

File statis disimpan dalam direktori akar web proyek. Direktori default adalah {content root}/wwwroot, tetapi dapat diubah dengan UseWebRoot metode . Untuk informasi selengkapnya, lihat Akar konten dan Akar web.

Metode CreateDefaultBuilder ini mengatur akar konten ke direktori saat ini:

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

Kode sebelumnya dibuat dengan templat aplikasi web.

File statis dapat diakses melalui jalur yang relatif terhadap akar web. Misalnya, templat proyek Aplikasi Web berisi beberapa folder dalam wwwroot folder:

  • wwwroot
    • css
    • js
    • lib

Pertimbangkan untuk membuat folder wwwroot/images dan menambahkan wwwroot/images/MyImage.jpg file. Format URI untuk mengakses file di images folder adalah https://<hostname>/images/<image_file_name>. Misalnya: https://localhost:5001/images/MyImage.jpg

Menyimpan file di direktori root web

Templat aplikasi web default memanggil UseStaticFiles metode di Startup.Configure, yang memungkinkan file statis dilayani:

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

Overload metode tanpa parameter UseStaticFiles menandai file di akar web sebagai dapat disajikan. Referensi wwwroot/images/MyImage.jpgmarkup berikut :

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

Dalam kode sebelumnya, karakter ~/ tilde mengacu ke root web.

Menyajikan file di luar akar web

Pertimbangkan hierarki direktori tempat file statis untuk dilayani berada di luar akar web:

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

Sebuah permintaan dapat mengakses file red-rose.jpg dengan mengonfigurasi Middleware File Statis sebagai berikut:

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

Dalam kode sebelumnya, hierarki direktori MyStaticFiles diekspos secara publik melalui segmen URI StaticFiles . Permintaan ke https://<hostname>/StaticFiles/images/red-rose.jpg menyajikan berkas red-rose.jpg.

Referensi markup berikut ini:

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

Mengatur header respons HTTP

Objek StaticFileOptions dapat digunakan untuk mengatur header respons HTTP. Selain mengonfigurasi penyajian file statis dari akar web, kode berikut mengatur Cache-Control header:

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

Kode sebelumnya menetapkan usia maksimal hingga 604800 detik (7 hari).

Header respons menunjukkan bahwa header Cache-Control telah ditambahkan

Otorisasi file statis

Templat ASP.NET Core memanggil UseStaticFiles sebelum memanggil UseAuthorization. Sebagian besar aplikasi mengikuti pola ini. Ketika middleware file statis dipanggil sebelum middleware otorisasi:

  • Tidak ada pemeriksaan otorisasi yang dilakukan pada file statis.
  • File statis yang dilayani oleh Middleware File Statis, seperti file di bawah wwwroot, dapat diakses secara publik.

Untuk menyajikan file statis berdasarkan otorisasi:

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.

Dalam kode sebelumnya, kebijakan otorisasi fallback mengharuskan semua pengguna diautentikasi. Titik akhir seperti pengontrol, Razor Halaman, dll yang menentukan persyaratan otorisasi mereka sendiri tidak menggunakan kebijakan otorisasi fallback. Misalnya, Razor halaman, pengontrol, atau metode aksi yang menggunakan [AllowAnonymous] atau [Authorize(PolicyName="MyPolicy")] lebih memilih atribut otorisasi yang diterapkan daripada kebijakan otorisasi fallback.

RequireAuthenticatedUser menambahkan DenyAnonymousAuthorizationRequirement ke instans saat ini, yang memastikan bahwa pengguna saat ini sudah diautentikasi.

Aset statis di bawah wwwroot dapat diakses secara publik karena Middleware File Statis default (app.UseStaticFiles();) dipanggil sebelum UseAuthentication. Aset statis di folder MyStaticFiles memerlukan autentikasi. Kode sampel menunjukkan ini.

Pendekatan alternatif untuk melayani file berdasarkan otorisasi adalah dengan:

  • Simpan di luar wwwroot dan direktori apa pun yang dapat diakses oleh Middleware File Statis.
  • Sajikan melalui metode tindakan tempat otorisasi diterapkan dan mengembalikan FileResult objek:
[Authorize]
public IActionResult BannerImage()
{
    var filePath = Path.Combine(
        _env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");

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

Penjelajahan direktori

Penelusuran direktori memungkinkan penampilan daftar direktori dalam direktori tertentu.

Penjelajahan direktori dinonaktifkan secara default karena alasan keamanan. Untuk informasi selengkapnya, lihat Pertimbangan keamanan untuk file statis.

Aktifkan penjelajahan direktori dengan:

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

Kode sebelumnya memungkinkan penjelajahan direktori folder wwwroot/images menggunakan URL https://<hostname>/MyImages, dengan tautan ke setiap file dan folder:

penjelajahan direktori

Menyediakan dokumen default

Mengatur halaman default memberi pengunjung titik awal di situs. Untuk melayani file default dari wwwroot tanpa memerlukan URL permintaan untuk menyertakan nama file, panggil UseDefaultFiles metode :

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 harus dipanggil sebelumnya UseStaticFiles untuk melayani file default. UseDefaultFiles adalah penulis ulang URL yang tidak melayani file.

Dengan UseDefaultFiles, permintaan ke folder dalam wwwroot mencari:

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

File pertama yang ditemukan dari daftar dilayani seolah-olah permintaan menyertakan nama file. URL browser terus mencerminkan URI yang diminta.

Kode berikut mengubah nama file default menjadi mydefault.html:

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

Kode berikut menunjukkan Startup.Configure dengan kode sebelumnya:

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

Gunakan UseFileServer untuk dokumen bawaan

UseFileServer menggabungkan fungsionalitas UseStaticFiles, UseDefaultFiles, dan secara UseDirectoryBrowseropsional .

Panggil app.UseFileServer untuk mengaktifkan penyajian file statis dan file default. Penjelajahan direktori tidak diaktifkan. Kode berikut menunjukkan Startup.Configure dengan 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();
    });
}

Kode berikut memungkinkan penyajian file statis, file default, dan penjelajahan direktori:

app.UseFileServer(enableDirectoryBrowsing: true);

Kode berikut menunjukkan Startup.Configure dengan kode sebelumnya:

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

Pertimbangkan hierarki direktori berikut:

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

Kode berikut memungkinkan penyajian file statis, file default, dan penjelajahan direktori dari 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 harus dipanggil ketika EnableDirectoryBrowsing nilai properti adalah true.

Menggunakan hierarki file dan kode sebelumnya, URL diselesaikan sebagai berikut:

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

Jika tidak ada file bernama "default" di direktori MyStaticFiles, https://<hostname>/StaticFiles akan menampilkan daftar isi direktori dengan tautan yang dapat diklik.

Daftar file statis

UseDefaultFiles dan UseDirectoryBrowser melakukan pengalihan sisi klien dari URI target tanpa trailing / ke URI target dengan trailing /. Misalnya, dari https://<hostname>/StaticFiles ke https://<hostname>/StaticFiles/. URL relatif dalam direktori StaticFiles tidak valid tanpa garis miring di akhir (/).

FileExtensionContentTypeProvider

Kelas FileExtensionContentTypeProvider berisi Mappings properti yang berfungsi sebagai pemetaan ekstensi file ke jenis konten MIME. Dalam sampel berikut, beberapa ekstensi file dipetakan ke jenis MIME yang diketahui. Ekstensi .rtf diganti, dan .mp4 dihapus:

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

Kode berikut menunjukkan Startup.Configure dengan kode sebelumnya:

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

Lihat Jenis konten MIME.

Jenis konten non-standar

Middleware File Statis memahami hampir 400 jenis konten file yang diketahui. Jika pengguna meminta file dengan jenis file yang tidak diketahui, Middleware File Statis meneruskan permintaan ke middleware berikutnya dalam alur. Jika tidak ada middleware yang menangani permintaan, respons 404 Tidak Ditemukan dikembalikan. Jika penjelajahan direktori diaktifkan, tautan ke file ditampilkan dalam daftar direktori.

Kode berikut memungkinkan penyajian jenis yang tidak diketahui dan merender file yang tidak diketahui sebagai gambar:

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

Kode berikut menunjukkan Startup.Configure dengan kode sebelumnya:

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

Dengan kode sebelumnya, permintaan untuk file dengan jenis konten yang tidak diketahui dikembalikan sebagai gambar.

Peringatan

Mengaktifkan ServeUnknownFileTypes adalah risiko keamanan. Ini dinonaktifkan secara default, dan penggunaannya tidak disarankan. FileExtensionContentTypeProvider menyediakan alternatif yang lebih aman untuk melayani file dengan ekstensi non-standar.

Menyajikan file dari beberapa lokasi

UseStaticFiles dan UseFileServer default ke penyedia file yang menunjuk ke wwwroot. Instans tambahan UseStaticFiles dan UseFileServer dapat disediakan dengan penyedia file lain untuk menyediakan file dari lokasi lain. Untuk informasi lebih lanjut, lihat masalah GitHub ini.

Pertimbangan keamanan untuk file statis

Peringatan

UseDirectoryBrowser dan UseStaticFiles dapat membocorkan rahasia. Menonaktifkan penjelajahan direktori dalam produksi sangat disarankan. Tinjau direktori mana yang diaktifkan dengan hati-hati melalui UseStaticFiles atau UseDirectoryBrowser. Seluruh direktori dan sub-direktorinya dapat diakses secara publik. Simpan file yang cocok untuk dilayani ke publik di direktori khusus, seperti <content_root>/wwwroot. Pisahkan file-file ini dari tampilan MVC, Razor Halaman, file konfigurasi, dll.

  • URL untuk konten yang diekspos dengan UseDirectoryBrowser dan UseStaticFiles tunduk pada sensitivitas kasus dan pembatasan karakter dari sistem file yang mendasar. Misalnya, Windows tidak peka huruf besar/kecil, tetapi macOS dan Linux tidak.

  • Aplikasi ASP.NET Core yang dihosting di IIS menggunakan ASP.NET Core Module untuk meneruskan semua permintaan ke app, termasuk permintaan berkas statis. Handler file statis IIS tidak digunakan dan tidak memiliki kesempatan untuk menangani permintaan.

  • Selesaikan langkah-langkah berikut di Manajer IIS untuk menghapus handler file statis IIS di tingkat server atau situs web:

    1. Navigasikan ke fitur Modul.
    2. Pilih StaticFileModule dalam daftar.
    3. Klik Hapus di bilah samping Tindakan.

Peringatan

Jika handler file statis IIS diaktifkan dan ASP.NET Core Module dikonfigurasi dengan salah, file statis dilayani. Ini terjadi, misalnya, jika file web.config tidak disebarkan.

  • Tempatkan file kode, termasuk .cs dan .cshtml, di luar akar web proyek aplikasi. Oleh karena itu, pemisahan logis dibuat antara konten sisi klien aplikasi dan kode berbasis server. Ini mencegah kode sisi server bocor.

Sumber Daya Tambahan: