ASP.NET Core の静的ファイル
注意
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
作成者: Rick Anderson
HTML、CSS、画像、JavaScript などの静的ファイルは、既定では ASP.NET Core アプリにより直接クライアントに提供される資産です。
この記事のガイダンスに追加されるまたは優先する Blazor 静的ファイルのガイダンスについては、「ASP.NET Core Blazor 静的ファイル」をご覧ください。
静的ファイルの提供
静的ファイルは、プロジェクトの Web ルート ディレクトリ内に格納されています。 既定のディレクトリは {content root}/wwwroot
ですが、UseWebRoot メソッドを使用して変更できます。 詳細については、「コンテンツ ルート」および「Web ルート」を参照してください。
CreateBuilder メソッドでは、コンテンツのルートが現在のディレクトリに設定されます。
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();
静的ファイルには、Web ルートに対する相対パスを使用してアクセスできます。 たとえば、Web アプリケーション プロジェクト テンプレートでは、wwwroot
フォルダー内に次のいくつかのフォルダーが含まれています。
wwwroot
css
js
lib
wwwroot/images/MyImage.jpg
ファイルを含むアプリについて考えてみましょう。 images
フォルダー内のファイルにアクセスするための URI 形式は https://<hostname>/images/<image_file_name>
です。 たとえば、https://localhost:5001/images/MyImage.jpg
のように指定します。
MapStaticAssets
高パフォーマンスの Web アプリを作成するには、ブラウザーへのアセット デリバリーを最適化する必要があります。 以下の最適化が考えられます。
- ファイルが変更されるか、ブラウザーでキャッシュがクリアされるまで、指定された資産が一度だけ提供されます。 ETag ヘッダーを設定する。
- アプリの更新後にブラウザーが以前のアセットや古くなったアセットを使用することを防ぐ。 Last-Modified ヘッダーを設定する。
- 適切なキャッシュ ヘッダーを設定する。
- キャッシュ ミドルウェアを使用する。
- 可能な場合は圧縮バージョンのアセットを提供する。
- CDN を使用してユーザーにより近いアセットを提供する。
- ブラウザーに提供される資産のサイズを最小化します。 この最適化には縮小は含まれません。
MapStaticAssets
は、アプリ内の静的アセットの配信を最適化するのに役立つミドルウェアです。 これは、Blazor、Razor Pages、MVC など、すべての UI フレームワークで動作するように設計されています。
UseStaticFiles
では静的ファイルも提供されますが、MapStaticAssets
と同じレベルの最適化は行われません。 UseStaticFiles
と MapStaticAssets
の比較については、「静的 Web アセット配信の最適化」を参照してください。
Web ルート内のファイルの提供
既定の Web アプリ テンプレートでは、Program.cs
内で MapStaticAssets
メソッドが呼び出されます。これにより、静的ファイルを提供できるようになります。
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();
UseStaticFiles
メソッドのパラメーターなしのオーバーロードによって、Web ルート内のファイルが提供可能とマークされます。 次のマークアップは、wwwroot/images/MyImage.jpg
を参照します。
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
上記のマークアップでは、チルダ文字 ~
が Web ルートを指します。
Web ルート外のファイルの提供
提供する静的ファイルが Web ルートの外にあるディレクトリ階層について考えます。
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
静的ファイル ミドルウェアを次のように構成すると、要求で red-rose.jpg
ファイルにアクセスできます。
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();
前述のコードでは、MyStaticFiles ディレクトリ階層は、StaticFiles URI セグメントでパブリックに公開されています。 https://<hostname>/StaticFiles/images/red-rose.jpg
の要求は、red-rose.jpg
ファイルを提供します。
次のマークアップは、MyStaticFiles/images/red-rose.jpg
を参照します。
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
複数の場所からファイルを提供するには、「複数の場所からファイルを提供する」を参照してください。
HTTP 応答ヘッダーの設定
StaticFileOptions オブジェクトを使用すると、HTTP 応答ヘッダーを設定できます。 Web ルートから提供される静的ファイルの構成に加えて、次のコードで 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();
上記のコードでは、静的ファイルをローカル キャッシュに 1 週間公開します。
静的ファイルの承認
ASP.NET Core テンプレートでは、UseAuthorization を呼び出す前に MapStaticAssets
が呼び出されます。 ほとんどのアプリがこのパターンに従います。 認可ミドルウェアの前に静的ファイル ミドルウェアが呼び出される場合:
- 静的ファイルに対して認可チェックは実行されません。
- 静的ファイル ミドルウェアによって提供される静的ファイル (
wwwroot
下にあるものなど) には、パブリックにアクセスできます。
認可に基づいて静的ファイルを提供するには:
- それらを
wwwroot
の外部に保存します。 UseAuthorization
を呼び出した後に、パスを指定してUseStaticFiles
を呼び出します。- フォールバック認可ポリシーを設定します。
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();
上記のコードでは、フォールバック認可ポリシーによって "すべて" のユーザーを認証することが要求されます。 独自の認可要件を指定する、コントローラー、Razor Pages などのエンドポイントでは、フォールバック認可ポリシーは使用されません。 たとえば、[AllowAnonymous]
や [Authorize(PolicyName="MyPolicy")]
を使用する Razor Pages、コントローラー、またはアクション メソッドでは、フォールバック認可ポリシーではなく適用された認可属性が使用されます。
RequireAuthenticatedUser により、現在のインスタンスに DenyAnonymousAuthorizationRequirement が追加されます。これにより、現在のユーザーが認証されます。
UseAuthentication
の前に既定の静的ファイル ミドルウェア (app.UseStaticFiles();
) が呼び出されるため、wwwroot
下の静的資産にはパブリックにアクセスできます。 MyStaticFiles フォルダー内の静的資産には認証が必要です。 これはサンプル コードで示されています。
認可に基づいてファイルを提供する別の方法:
wwwroot
や静的ファイル ミドルウェアがアクセスできる任意のディレクトリの外にファイルを配置します。承認が適用されるアクション メソッドを使用して提供し、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"); } }
上記の方法では、ファイルごとにページまたはエンドポイントが必要です。 次のコードは、認証されたユーザーのファイルを返すか、ファイルをアップロードします。
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 では、アップロードにメモリ バッファーを使用します。 大きなファイルを処理する場合は、ストリーミングを使用します。 詳細については、「ストリーミングを使用して大きいファイルをアップロードする」をご覧ください。
完全なサンプルについては、StaticFileAuth GitHub フォルダーをご覧ください。
ディレクトリ参照
ディレクトリ参照を使用すると、指定したディレクトリ内のディレクトリを一覧表示できます。
ディレクトリ参照は、セキュリティ上の理由から既定で無効になっています。 詳細については、「静的ファイルのセキュリティに関する注意点」を参照してください。
AddDirectoryBrowser と 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();
上記のコードでは、URL https://<hostname>/MyImages
が使用され、各ファイルおよびフォルダーへのリンクを含む wwwroot/images フォルダーのディレクトリが参照できるようになります。
AddDirectoryBrowser
により、HtmlEncoder など、ディレクトリ参照ミドルウェアで必要なサービスが追加されます。 これらのサービスは、AddRazorPages などの他の呼び出しによって追加することもできますが、すべてのアプリでサービスを確実に追加できるように、AddDirectoryBrowser
を呼び出すことをお勧めします。
既定のドキュメントの提供
既定のページを設定すると、サイトのビジターの開始点になります。 要求 URL にファイルの名前を含めずに wwwroot
から既定のファイルを提供するには、UseDefaultFiles メソッドを呼び出します。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
既定のファイルを提供するには、UseStaticFiles
の前に UseDefaultFiles
が呼び出される必要があります。 UseDefaultFiles
は、ファイルを提供しない URL リライターです。
UseDefaultFiles
を使用すると、wwwroot
内のフォルダーの要求では以下のファイルが検索されます。
default.htm
default.html
index.htm
index.html
一覧で見つかった最初のファイルは、要求にファイル名が含まれていたかのように提供されます。 ブラウザー URL は、要求された URI を反映し続けます。 たとえば、サンプル アプリでは、https://localhost:<port>/def/
への要求で wwwroot/def
から default.html
が提供されます。
次のコードによって、既定のファイル名が 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
UseFileServer は、UseStaticFiles
、UseDefaultFiles
、およびオプションとして UseDirectoryBrowser
の機能を兼ね備えています。
app.UseFileServer
を呼び出すと、静的ファイルと既定ファイルが提供できるようになります。 ディレクトリ参照は有効になりません。
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();
次のコードによって、静的ファイルの提供、既定ファイル、ディレクトリ参照が有効になります。
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();
次のディレクトリ階層があるとします。
wwwroot
css
images
js
MyStaticFiles
defaultFiles
default.html
image3.png
images
MyImage.jpg
次のコードによって、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();
EnableDirectoryBrowsing
プロパティの値が true
であるときは、AddDirectoryBrowser を呼び出す必要があります。
前述のファイル階層とコードを使用すると、URL は次のように解決されます。
URI | 回答 |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
ディレクトリ一覧 |
https://<hostname>/StaticFiles/defaultFiles |
MyStaticFiles/defaultFiles/default.html |
https://<hostname>/StaticFiles/defaultFiles/image3.png |
MyStaticFiles/defaultFiles//image3.png |
MyStaticFiles ディレクトリに既定の名前のファイルが存在しない場合、https://<hostname>/StaticFiles
によってクリック可能なリンクを含むディレクトリの一覧が返されます。
UseDefaultFiles および UseDirectoryBrowser では、末尾の /
がないターゲット URI から末尾の /
があるターゲット URI へのクライアント側リダイレクトが実行されます。 たとえば、https://<hostname>/StaticFiles
は https://<hostname>/StaticFiles/
になります。 StaticFiles ディレクトリ内の相対 URL は、DefaultFilesOptions の RedirectToAppendTrailingSlash オプションを使用しない限り、末尾のスラッシュ (/
) がないと無効です。
FileExtensionContentTypeProvider
FileExtensionContentTypeProvider クラスには、MIME コンテンツ タイプへのファイル拡張子のマッピングとして機能する Mappings プロパティが含まれています。 次の例では、いくつかのファイル拡張子が、既知の MIME タイプにマッピングされています。 .rtf 拡張子は置換され、 .mp4 は削除されています。
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();
「MIME content types」 (MIME コンテンツ タイプ) を参照してください。
非標準のコンテンツ タイプ
静的ファイル ミドルウェアでは、約 400 の既知のファイル コンテンツ タイプが認識されています。 ユーザーがファイルの種類が不明なファイルを要求した場合、静的ファイル ミドルウェアでその要求がパイプラインの次のミドルウェアに渡されます。 ミドルウェアで要求が処理されない場合、404 見つかりません という応答が返されます。 ディレクトリ参照が有効になっている場合、ディレクトリ一覧にファイルへのリンクが表示されます。
次のコードによって、不明なタイプを提供できるようにし、不明なファイルをイメージとしてレンダリングします。
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();
上記のコードでは、不明なコンテンツ タイプ ファイルに対する要求は、イメージとして返されます。
警告
ServeUnknownFileTypes を有効にすると、セキュリティ上リスクとなります。 これは既定では無効で、使用は推奨されていません。 非標準の拡張子のファイルを提供する場合、より安全な代替となるのは、FileExtensionContentTypeProvider です。
複数の場所からファイルを提供する
/MyStaticFiles/image3.png
ファイルを表示する次の Razor ページについて考えます。
@page
<p> Test /MyStaticFiles/image3.png</p>
<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">
UseStaticFiles
と UseFileServer
の既定では、wwwroot
をポイントするファイル プロバイダーが作成されます。 UseStaticFiles
および UseFileServer
の追加インスタンスを作成して他のファイル プロバイダーを使用すると、他の場所からファイルを提供することができます。 次の例では、UseStaticFiles
を 2 回呼び出して、wwwroot
と MyStaticFiles
の両方からファイルを提供します。
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});
上のコードを使います。
/MyStaticFiles/image3.png
ファイルが表示されます。- イメージ タグ ヘルパー AppendVersion は、タグ ヘルパーが WebRootFileProvider に依存しているため、適用されません。
WebRootFileProvider
はMyStaticFiles
フォルダーを含むように更新されていません。
次のコードは WebRootFileProvider
を更新し、イメージ タグ ヘルパーがバージョンを提供できるようにします。
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();
Note
上記の方法は、Razor Pages および MVC アプリに適用されます。 Blazor Web App に適用されるガイダンスについては、「ASP.NET Core Blazor 静的ファイル」をご覧ください。
静的ファイルのセキュリティに関する注意点
警告
UseDirectoryBrowser
と UseStaticFiles
では、機密データが漏洩することがあります。 本番では、ディレクトリ参照を無効にすることが、強く推奨されます。 UseStaticFiles
や UseDirectoryBrowser
でどのディレクトリが有効になっているか、慎重にご確認ください。 ディレクトリ全体とそのサブディレクトリが、パブリックにアクセス可能になります。 ファイルは、パブリックに提供するのに適した、<content_root>/wwwroot
などの専用ディレクトリに格納します。 これらのファイルは、MVC ビュー、Razor Pages、構成ファイルなどとは別にします。
UseDirectoryBrowser
、UseStaticFiles
、およびMapStaticAssets
で公開されるコンテンツの URL では、大文字と小文字が区別され、基になるファイル システムの文字制限の影響を受けます。 たとえば、Windows では大文字と小文字が区別されませんが、macOS と Linux では区別されます。IIS でホストされている ASP.NET Core アプリは、ASP.NET Core モジュールを使用して、静的ファイルの要求を含む、すべての要求をアプリに転送します。 IIS の静的ファイル ハンドラーは使用されず、要求を処理することはできません。
IIS マネージャーで次の手順を実行し、サーバーまたは Web サイト レベルで IIS の静的ファイル ハンドラーを削除します。
- [モジュール] 機能に移動します。
- 一覧の [StaticFileModule] を選択します。
- [アクション] サイドバーで、 [削除] をクリックします。
警告
IIS の静的ファイル ハンドラーが有効になっており、かつ、ASP.NET Core モジュールが正しく構成されていない場合、静的ファイルにサービスが提供されます。 これは、たとえば、web.config ファイルが配置されていない場合などで発生します。
- アプリ プロジェクトの Web ルートの外に、コード ファイル (
.cs
と.cshtml
を含む) を配置します。 これにより、アプリのクライアント側コンテンツとサーバー ベースのコードの間で、論理的な分離が作成されます。 これによって、サーバー側のコードが漏洩するのを防ぎます。
IWebHostEnvironment.WebRootPath を更新して wwwroot の外部のファイルを提供する
IWebHostEnvironment.WebRootPath が wwwroot
以外のフォルダーに設定されている場合:
- 開発環境では、
wwwroot
と更新されたIWebHostEnvironment.WebRootPath
の両方で見つかった静的資産がwwwroot
から提供されます。 - 開発以外のどの環境でも、重複する静的資産は、更新された
IWebHostEnvironment.WebRootPath
フォルダーから提供されます。
空の Web テンプレートを使用して作成された Web アプリについて考えてみましょう。
wwwroot
とwwwroot-custom
にIndex.html
ファイルが含まれる。WebRootPath = "wwwroot-custom"
を設定する、更新された次のProgram.cs
ファイルがある。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();
上記のコードで、/
に要求を行うと:
- 開発環境では
wwwroot/Index.html
が返される - 開発以外のどの環境でも
wwwroot-custom/Index.html
が返される
確実に wwwroot-custom
の資産が返されるようにするには、以下のいずれかの方法を使用します。
wwwroot
内の重複する名前付き資産を削除します。Properties/launchSettings.json
内の"ASPNETCORE_ENVIRONMENT"
を"Development"
以外の任意の値に設定します。プロジェクト ファイルで
<StaticWebAssetsEnabled>false</StaticWebAssetsEnabled>
を設定して、静的 Web 資産を完全に無効にします。 警告: 静的 Web 資産を無効にすると、Razor クラス ライブラリが無効になります。プロジェクト ファイルに次の XML を追加します。
<ItemGroup> <Content Remove="wwwroot\**" /> </ItemGroup>
次のコードによって、IWebHostEnvironment.WebRootPath
は開発以外の値に更新され、重複するコンテンツが wwwroot
ではなく wwwroot-custom
から返されることが保証されます。
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();
その他のリソース
作成者: Rick Anderson
HTML、CSS、画像、JavaScript などの静的ファイルは、既定では ASP.NET Core アプリにより直接クライアントに提供される資産です。
静的ファイルの提供
静的ファイルは、プロジェクトの Web ルート ディレクトリ内に格納されています。 既定のディレクトリは {content root}/wwwroot
ですが、UseWebRoot メソッドを使用して変更できます。 詳細については、「コンテンツ ルート」および「Web ルート」を参照してください。
CreateBuilder メソッドでは、コンテンツのルートが現在のディレクトリに設定されます。
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();
静的ファイルには、Web ルートに対する相対パスを使用してアクセスできます。 たとえば、Web アプリケーション プロジェクト テンプレートでは、wwwroot
フォルダー内に次のいくつかのフォルダーが含まれています。
wwwroot
css
js
lib
wwwroot/images フォルダーを作成し、wwwroot/images/MyImage.jpg
ファイルを追加する場合を考えてみます。 images
フォルダー内のファイルにアクセスするための URI 形式は https://<hostname>/images/<image_file_name>
です。 たとえば、https://localhost:5001/images/MyImage.jpg
Web ルート内のファイルの提供
既定の Web アプリ テンプレートでは、Program.cs
内で UseStaticFiles メソッドが呼び出されます。これにより、静的ファイルを提供できるようになります。
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();
UseStaticFiles
メソッドのパラメーターなしのオーバーロードによって、Web ルート内のファイルが提供可能とマークされます。 次のマークアップは、wwwroot/images/MyImage.jpg
を参照します。
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
上記のマークアップでは、チルダ文字 ~
が Web ルートを指します。
Web ルート外のファイルの提供
提供する静的ファイルが Web ルートの外にあるディレクトリ階層について考えます。
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
静的ファイル ミドルウェアを次のように構成すると、要求で red-rose.jpg
ファイルにアクセスできます。
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();
前述のコードでは、MyStaticFiles ディレクトリ階層は、StaticFiles URI セグメントでパブリックに公開されています。 https://<hostname>/StaticFiles/images/red-rose.jpg
の要求は、red-rose.jpg
ファイルを提供します。
次のマークアップは、MyStaticFiles/images/red-rose.jpg
を参照します。
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
複数の場所からファイルを提供するには、「複数の場所からファイルを提供する」を参照してください。
HTTP 応答ヘッダーの設定
StaticFileOptions オブジェクトを使用すると、HTTP 応答ヘッダーを設定できます。 Web ルートから提供される静的ファイルの構成に加えて、次のコードで 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();
上記のコードでは、静的ファイルをローカル キャッシュに 1 週間 (604800 秒) 公開します。
静的ファイルの承認
ASP.NET Core テンプレートでは、UseAuthorization を呼び出す前に UseStaticFiles が呼び出されます。 ほとんどのアプリがこのパターンに従います。 認可ミドルウェアの前に静的ファイル ミドルウェアが呼び出される場合:
- 静的ファイルに対して認可チェックは実行されません。
- 静的ファイル ミドルウェアによって提供される静的ファイル (
wwwroot
下にあるものなど) には、パブリックにアクセスできます。
認可に基づいて静的ファイルを提供するには:
- それらを
wwwroot
の外部に保存します。 UseAuthorization
を呼び出した後に、パスを指定してUseStaticFiles
を呼び出します。- フォールバック認可ポリシーを設定します。
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();
上記のコードでは、フォールバック認可ポリシーによって "すべて" のユーザーを認証することが要求されます。 独自の認可要件を指定する、コントローラー、Razor Pages などのエンドポイントでは、フォールバック認可ポリシーは使用されません。 たとえば、[AllowAnonymous]
や [Authorize(PolicyName="MyPolicy")]
を使用する Razor Pages、コントローラー、またはアクション メソッドでは、フォールバック認可ポリシーではなく適用された認可属性が使用されます。
RequireAuthenticatedUser により、現在のインスタンスに DenyAnonymousAuthorizationRequirement が追加されます。これにより、現在のユーザーが認証されます。
UseAuthentication
の前に既定の静的ファイル ミドルウェア (app.UseStaticFiles();
) が呼び出されるため、wwwroot
下の静的資産にはパブリックにアクセスできます。 MyStaticFiles フォルダー内の静的資産には認証が必要です。 これはサンプル コードで示されています。
認可に基づいてファイルを提供する別の方法:
wwwroot
や静的ファイル ミドルウェアがアクセスできる任意のディレクトリの外にファイルを配置します。承認が適用されるアクション メソッドを使用して提供し、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"); } }
上記の方法では、ファイルごとにページまたはエンドポイントが必要です。 次のコードは、認証されたユーザーのファイルを返すか、ファイルをアップロードします。
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();
完全なサンプルについては、StaticFileAuth GitHub フォルダーをご覧ください。
ディレクトリ参照
ディレクトリ参照を使用すると、指定したディレクトリ内のディレクトリを一覧表示できます。
ディレクトリ参照は、セキュリティ上の理由から既定で無効になっています。 詳細については、「静的ファイルのセキュリティに関する注意点」を参照してください。
AddDirectoryBrowser と 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();
上記のコードでは、URL https://<hostname>/MyImages
が使用され、各ファイルおよびフォルダーへのリンクを含む wwwroot/images フォルダーのディレクトリが参照できるようになります。
AddDirectoryBrowser
により、HtmlEncoder など、ディレクトリ参照ミドルウェアで必要なサービスが追加されます。 これらのサービスは、AddRazorPages などの他の呼び出しによって追加することもできますが、すべてのアプリでサービスを確実に追加できるように、AddDirectoryBrowser
を呼び出すことをお勧めします。
既定のドキュメントの提供
既定のページを設定すると、サイトのビジターの開始点になります。 要求 URL にファイルの名前を含めずに wwwroot
から既定のファイルを提供するには、UseDefaultFiles メソッドを呼び出します。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
既定のファイルを提供するには、UseStaticFiles
の前に UseDefaultFiles
が呼び出される必要があります。 UseDefaultFiles
は、ファイルを提供しない URL リライターです。
UseDefaultFiles
を使用すると、wwwroot
内のフォルダーの要求では以下のファイルが検索されます。
default.htm
default.html
index.htm
index.html
一覧で見つかった最初のファイルは、要求にファイル名が含まれていたかのように提供されます。 ブラウザー URL は、要求された URI を反映し続けます。
次のコードによって、既定のファイル名が 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
UseFileServer は、UseStaticFiles
、UseDefaultFiles
、およびオプションとして UseDirectoryBrowser
の機能を兼ね備えています。
app.UseFileServer
を呼び出すと、静的ファイルと既定ファイルが提供できるようになります。 ディレクトリ参照は有効になりません。
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();
次のコードによって、静的ファイルの提供、既定ファイル、ディレクトリ参照が有効になります。
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();
次のディレクトリ階層があるとします。
wwwroot
css
images
js
MyStaticFiles
images
MyImage.jpg
default.html
次のコードによって、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();
EnableDirectoryBrowsing
プロパティの値が true
であるときは、AddDirectoryBrowser を呼び出す必要があります。
前述のファイル階層とコードを使用すると、URL は次のように解決されます。
URI | 応答 |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
MyStaticFiles/default.html |
MyStaticFiles ディレクトリに既定の名前のファイルが存在しない場合、https://<hostname>/StaticFiles
によってクリック可能なリンクを含むディレクトリの一覧が返されます。
UseDefaultFiles および UseDirectoryBrowser では、末尾の /
がないターゲット URI から末尾の /
があるターゲット URI へのクライアント側リダイレクトが実行されます。 たとえば、https://<hostname>/StaticFiles
は https://<hostname>/StaticFiles/
になります。 StaticFiles ディレクトリ内の相対 URL は、DefaultFilesOptions の RedirectToAppendTrailingSlash オプションを使用しない限り、末尾のスラッシュ (/
) がないと無効です。
FileExtensionContentTypeProvider
FileExtensionContentTypeProvider クラスには、MIME コンテンツ タイプへのファイル拡張子のマッピングを行う Mappings
プロパティが含まれます。 次の例では、いくつかのファイル拡張子が、既知の MIME タイプにマッピングされています。 .rtf 拡張子は置換され、 .mp4 は削除されています。
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();
「MIME content types」 (MIME コンテンツ タイプ) を参照してください。
非標準のコンテンツ タイプ
静的ファイル ミドルウェアでは、約 400 の既知のファイル コンテンツ タイプが認識されています。 ユーザーがファイルの種類が不明なファイルを要求した場合、静的ファイル ミドルウェアでその要求がパイプラインの次のミドルウェアに渡されます。 ミドルウェアで要求が処理されない場合、404 見つかりません という応答が返されます。 ディレクトリ参照が有効になっている場合、ディレクトリ一覧にファイルへのリンクが表示されます。
次のコードによって、不明なタイプを提供できるようにし、不明なファイルをイメージとしてレンダリングします。
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();
上記のコードでは、不明なコンテンツ タイプ ファイルに対する要求は、イメージとして返されます。
警告
ServeUnknownFileTypes を有効にすると、セキュリティ上リスクとなります。 これは既定では無効で、使用は推奨されていません。 非標準の拡張子のファイルを提供する場合、より安全な代替となるのは、FileExtensionContentTypeProvider です。
複数の場所からファイルを提供する
/MyStaticFiles/image3.png
ファイルを表示する次の Razor ページについて考えます。
@page
<p> Test /MyStaticFiles/image3.png</p>
<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">
UseStaticFiles
と UseFileServer
の既定では、wwwroot
をポイントするファイル プロバイダーが作成されます。 UseStaticFiles
および UseFileServer
の追加インスタンスを作成して他のファイル プロバイダーを使用すると、他の場所からファイルを提供することができます。 次の例では、UseStaticFiles
を 2 回呼び出して、wwwroot
と MyStaticFiles
の両方からファイルを提供します。
app.UseStaticFiles(); // Serve files from wwwroot
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});
上のコードを使います。
/MyStaticFiles/image3.png
ファイルが表示されます。- イメージ タグ ヘルパー AppendVersion は、タグ ヘルパーが WebRootFileProvider に依存しているため、適用されません。
WebRootFileProvider
はMyStaticFiles
フォルダーを含むように更新されていません。
次のコードは WebRootFileProvider
を更新し、イメージ タグ ヘルパーがバージョンを提供できるようにします。
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();
Note
上記の方法は、Razor Pages および MVC アプリに適用されます。 Blazor Web App に適用されるガイダンスについては、「ASP.NET Core Blazor 静的ファイル」をご覧ください。
静的ファイルのセキュリティに関する注意点
警告
UseDirectoryBrowser
と UseStaticFiles
では、機密データが漏洩することがあります。 本番では、ディレクトリ参照を無効にすることが、強く推奨されます。 UseStaticFiles
や UseDirectoryBrowser
でどのディレクトリが有効になっているか、慎重にご確認ください。 ディレクトリ全体とそのサブディレクトリが、パブリックにアクセス可能になります。 ファイルは、パブリックに提供するのに適した、<content_root>/wwwroot
などの専用ディレクトリに格納します。 これらのファイルは、MVC ビュー、Razor Pages、構成ファイルなどとは別にします。
UseDirectoryBrowser
とUseStaticFiles
で公開されるコンテンツの URL では、大文字と小文字が区別され、基になるファイル システムの文字制限の影響を受けます。 たとえば、Windows では大文字と小文字が区別されませんが、macOS と Linux では区別されます。IIS でホストされている ASP.NET Core アプリは、ASP.NET Core モジュールを使用して、静的ファイルの要求を含む、すべての要求をアプリに転送します。 IIS の静的ファイル ハンドラーは使用されず、要求を処理することはできません。
IIS マネージャーで次の手順を実行し、サーバーまたは Web サイト レベルで IIS の静的ファイル ハンドラーを削除します。
- [モジュール] 機能に移動します。
- 一覧の [StaticFileModule] を選択します。
- [アクション] サイドバーで、 [削除] をクリックします。
警告
IIS の静的ファイル ハンドラーが有効になっており、かつ、ASP.NET Core モジュールが正しく構成されていない場合、静的ファイルにサービスが提供されます。 これは、たとえば、web.config ファイルが配置されていない場合などで発生します。
- アプリ プロジェクトの Web ルートの外に、コード ファイル (
.cs
と.cshtml
を含む) を配置します。 これにより、アプリのクライアント側コンテンツとサーバー ベースのコードの間で、論理的な分離が作成されます。 これによって、サーバー側のコードが漏洩するのを防ぎます。
IWebHostEnvironment.WebRootPath を更新して wwwroot の外部のファイルを提供する
IWebHostEnvironment.WebRootPath が wwwroot
以外のフォルダーに設定されている場合:
- 開発環境では、
wwwroot
と更新されたIWebHostEnvironment.WebRootPath
の両方で見つかった静的資産がwwwroot
から提供されます。 - 開発以外のどの環境でも、重複する静的資産は、更新された
IWebHostEnvironment.WebRootPath
フォルダーから提供されます。
空の Web テンプレートを使用して作成された Web アプリについて考えてみましょう。
wwwroot
とwwwroot-custom
にIndex.html
ファイルが含まれる。WebRootPath = "wwwroot-custom"
を設定する、更新された次のProgram.cs
ファイルがある。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();
上記のコードで、/
に要求を行うと:
- 開発環境では
wwwroot/Index.html
が返される - 開発以外のどの環境でも
wwwroot-custom/Index.html
が返される
確実に wwwroot-custom
の資産が返されるようにするには、以下のいずれかの方法を使用します。
wwwroot
内の重複する名前付き資産を削除します。Properties/launchSettings.json
内の"ASPNETCORE_ENVIRONMENT"
を"Development"
以外の任意の値に設定します。プロジェクト ファイルで
<StaticWebAssetsEnabled>false</StaticWebAssetsEnabled>
を設定して、静的 Web 資産を完全に無効にします。 警告: 静的 Web 資産を無効にすると、Razor クラス ライブラリが無効になります。プロジェクト ファイルに次の JSON を追加します。
<ItemGroup> <Content Remove="wwwroot\**" /> </ItemGroup>
次のコードによって、IWebHostEnvironment.WebRootPath
は開発以外の値に更新され、重複するコンテンツが wwwroot
ではなく wwwroot-custom
から返されることが保証されます。
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();
その他のリソース
作成者: Rick Anderson および Kirk Larkin
HTML、CSS、画像、JavaScript などの静的ファイルは、既定では ASP.NET Core アプリにより直接クライアントに提供される資産です。
静的ファイルの提供
静的ファイルは、プロジェクトの Web ルート ディレクトリ内に格納されています。 既定のディレクトリは {content root}/wwwroot
ですが、UseWebRoot メソッドを使用して変更できます。 詳細については、「コンテンツ ルート」および「Web ルート」を参照してください。
CreateBuilder メソッドでは、コンテンツのルートが現在のディレクトリに設定されます。
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();
静的ファイルには、Web ルートに対する相対パスを使用してアクセスできます。 たとえば、Web アプリケーション プロジェクト テンプレートでは、wwwroot
フォルダー内に次のいくつかのフォルダーが含まれています。
wwwroot
css
js
lib
wwwroot/images フォルダーを作成し、wwwroot/images/MyImage.jpg
ファイルを追加する場合を考えてみます。 images
フォルダー内のファイルにアクセスするための URI 形式は https://<hostname>/images/<image_file_name>
です。 たとえば、https://localhost:5001/images/MyImage.jpg
Web ルート内のファイルの提供
既定の Web アプリ テンプレートでは、Program.cs
内で UseStaticFiles メソッドが呼び出されます。これにより、静的ファイルを提供できるようになります。
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();
UseStaticFiles
メソッドのパラメーターなしのオーバーロードによって、Web ルート内のファイルが提供可能とマークされます。 次のマークアップは、wwwroot/images/MyImage.jpg
を参照します。
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
上記のマークアップでは、チルダ文字 ~
が Web ルートを指します。
Web ルート外のファイルの提供
提供する静的ファイルが Web ルートの外にあるディレクトリ階層について考えます。
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
静的ファイル ミドルウェアを次のように構成すると、要求で red-rose.jpg
ファイルにアクセスできます。
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();
前述のコードでは、MyStaticFiles ディレクトリ階層は、StaticFiles URI セグメントでパブリックに公開されています。 https://<hostname>/StaticFiles/images/red-rose.jpg
の要求は、red-rose.jpg
ファイルを提供します。
次のマークアップは、MyStaticFiles/images/red-rose.jpg
を参照します。
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
複数の場所からファイルを提供するには、「複数の場所からファイルを提供する」を参照してください。
HTTP 応答ヘッダーの設定
StaticFileOptions オブジェクトを使用すると、HTTP 応答ヘッダーを設定できます。 Web ルートから提供される静的ファイルの構成に加えて、次のコードで 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();
上記のコードでは、静的ファイルをローカル キャッシュに 1 週間 (604800 秒) 公開します。
静的ファイルの承認
ASP.NET Core テンプレートでは、UseAuthorization を呼び出す前に UseStaticFiles が呼び出されます。 ほとんどのアプリがこのパターンに従います。 認可ミドルウェアの前に静的ファイル ミドルウェアが呼び出される場合:
- 静的ファイルに対して認可チェックは実行されません。
- 静的ファイル ミドルウェアによって提供される静的ファイル (
wwwroot
下にあるものなど) には、パブリックにアクセスできます。
認可に基づいて静的ファイルを提供するには:
- それらを
wwwroot
の外部に保存します。 UseAuthorization
を呼び出した後に、パスを指定してUseStaticFiles
を呼び出します。- フォールバック認可ポリシーを設定します。
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();
上記のコードでは、フォールバック認可ポリシーによって "すべて" のユーザーを認証することが要求されます。 独自の認可要件を指定する、コントローラー、Razor Pages などのエンドポイントでは、フォールバック認可ポリシーは使用されません。 たとえば、[AllowAnonymous]
や [Authorize(PolicyName="MyPolicy")]
を使用する Razor Pages、コントローラー、またはアクション メソッドでは、フォールバック認可ポリシーではなく適用された認可属性が使用されます。
RequireAuthenticatedUser により、現在のインスタンスに DenyAnonymousAuthorizationRequirement が追加されます。これにより、現在のユーザーが認証されます。
UseAuthentication
の前に既定の静的ファイル ミドルウェア (app.UseStaticFiles();
) が呼び出されるため、wwwroot
下の静的資産にはパブリックにアクセスできます。 MyStaticFiles フォルダー内の静的資産には認証が必要です。 これはサンプル コードで示されています。
認可に基づいてファイルを提供する別の方法:
wwwroot
や静的ファイル ミドルウェアがアクセスできる任意のディレクトリの外にファイルを配置します。- 承認が適用されるアクション メソッドを使用して提供し、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");
}
}
ディレクトリ参照
ディレクトリ参照を使用すると、指定したディレクトリ内のディレクトリを一覧表示できます。
ディレクトリ参照は、セキュリティ上の理由から既定で無効になっています。 詳細については、「静的ファイルのセキュリティに関する注意点」を参照してください。
AddDirectoryBrowser と 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();
上記のコードでは、URL https://<hostname>/MyImages
が使用され、各ファイルおよびフォルダーへのリンクを含む wwwroot/images フォルダーのディレクトリが参照できるようになります。
AddDirectoryBrowser
により、HtmlEncoder など、ディレクトリ参照ミドルウェアで必要なサービスが追加されます。 これらのサービスは、AddRazorPages などの他の呼び出しによって追加することもできますが、すべてのアプリでサービスを確実に追加できるように、AddDirectoryBrowser
を呼び出すことをお勧めします。
既定のドキュメントの提供
既定のページを設定すると、サイトのビジターの開始点になります。 要求 URL にファイルの名前を含めずに wwwroot
から既定のファイルを提供するには、UseDefaultFiles メソッドを呼び出します。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
既定のファイルを提供するには、UseStaticFiles
の前に UseDefaultFiles
が呼び出される必要があります。 UseDefaultFiles
は、ファイルを提供しない URL リライターです。
UseDefaultFiles
を使用すると、wwwroot
内のフォルダーの要求では以下のファイルが検索されます。
default.htm
default.html
index.htm
index.html
一覧で見つかった最初のファイルは、要求にファイル名が含まれていたかのように提供されます。 ブラウザー URL は、要求された URI を反映し続けます。
次のコードによって、既定のファイル名が 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
UseFileServer は、UseStaticFiles
、UseDefaultFiles
、およびオプションとして UseDirectoryBrowser
の機能を兼ね備えています。
app.UseFileServer
を呼び出すと、静的ファイルと既定ファイルが提供できるようになります。 ディレクトリ参照は有効になりません。
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();
次のコードによって、静的ファイルの提供、既定ファイル、ディレクトリ参照が有効になります。
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();
次のディレクトリ階層があるとします。
wwwroot
css
images
js
MyStaticFiles
images
MyImage.jpg
default.html
次のコードによって、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();
EnableDirectoryBrowsing
プロパティの値が true
であるときは、AddDirectoryBrowser を呼び出す必要があります。
前述のファイル階層とコードを使用すると、URL は次のように解決されます。
URI | 応答 |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
MyStaticFiles/default.html |
MyStaticFiles ディレクトリに既定の名前のファイルが存在しない場合、https://<hostname>/StaticFiles
によってクリック可能なリンクを含むディレクトリの一覧が返されます。
UseDefaultFiles および UseDirectoryBrowser では、末尾の /
がないターゲット URI から末尾の /
があるターゲット URI へのクライアント側リダイレクトが実行されます。 たとえば、https://<hostname>/StaticFiles
は https://<hostname>/StaticFiles/
になります。 StaticFiles ディレクトリ内の相対 URL は、DefaultFilesOptions の RedirectToAppendTrailingSlash オプションを使用しない限り、末尾のスラッシュ (/
) がないと無効です。
FileExtensionContentTypeProvider
FileExtensionContentTypeProvider クラスには、MIME コンテンツ タイプへのファイル拡張子のマッピングを行う Mappings
プロパティが含まれます。 次の例では、いくつかのファイル拡張子が、既知の MIME タイプにマッピングされています。 .rtf 拡張子は置換され、 .mp4 は削除されています。
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();
「MIME content types」 (MIME コンテンツ タイプ) を参照してください。
非標準のコンテンツ タイプ
静的ファイル ミドルウェアでは、約 400 の既知のファイル コンテンツ タイプが認識されています。 ユーザーがファイルの種類が不明なファイルを要求した場合、静的ファイル ミドルウェアでその要求がパイプラインの次のミドルウェアに渡されます。 ミドルウェアで要求が処理されない場合、404 見つかりません という応答が返されます。 ディレクトリ参照が有効になっている場合、ディレクトリ一覧にファイルへのリンクが表示されます。
次のコードによって、不明なタイプを提供できるようにし、不明なファイルをイメージとしてレンダリングします。
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();
上記のコードでは、不明なコンテンツ タイプ ファイルに対する要求は、イメージとして返されます。
警告
ServeUnknownFileTypes を有効にすると、セキュリティ上リスクとなります。 これは既定では無効で、使用は推奨されていません。 非標準の拡張子のファイルを提供する場合、より安全な代替となるのは、FileExtensionContentTypeProvider です。
複数の場所からファイルを提供する
/MyStaticFiles/image3.png
ファイルを表示する次の Razor ページについて考えます。
@page
<p> Test /MyStaticFiles/image3.png</p>
<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">
UseStaticFiles
と UseFileServer
の既定では、wwwroot
をポイントするファイル プロバイダーが作成されます。 UseStaticFiles
および UseFileServer
の追加インスタンスを作成して他のファイル プロバイダーを使用すると、他の場所からファイルを提供することができます。 次の例では、UseStaticFiles
を 2 回呼び出して、wwwroot
と MyStaticFiles
の両方からファイルを提供します。
app.UseStaticFiles(); // Serve files from wwwroot
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});
上のコードを使います。
/MyStaticFiles/image3.png
ファイルが表示されます。- イメージ タグ ヘルパー AppendVersion は、タグ ヘルパーが WebRootFileProvider に依存しているため、適用されません。
WebRootFileProvider
はMyStaticFiles
フォルダーを含むように更新されていません。
次のコードは WebRootFileProvider
を更新し、イメージ タグ ヘルパーがバージョンを提供できるようにします。
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();
静的ファイルのセキュリティに関する注意点
警告
UseDirectoryBrowser
と UseStaticFiles
では、機密データが漏洩することがあります。 本番では、ディレクトリ参照を無効にすることが、強く推奨されます。 UseStaticFiles
や UseDirectoryBrowser
でどのディレクトリが有効になっているか、慎重にご確認ください。 ディレクトリ全体とそのサブディレクトリが、パブリックにアクセス可能になります。 ファイルは、パブリックに提供するのに適した、<content_root>/wwwroot
などの専用ディレクトリに格納します。 これらのファイルは、MVC ビュー、Razor Pages、構成ファイルなどとは別にします。
UseDirectoryBrowser
とUseStaticFiles
で公開されるコンテンツの URL では、大文字と小文字が区別され、基になるファイル システムの文字制限の影響を受けます。 たとえば、Windows では大文字と小文字が区別されませんが、macOS と Linux では区別されます。IIS でホストされている ASP.NET Core アプリは、ASP.NET Core モジュールを使用して、静的ファイルの要求を含む、すべての要求をアプリに転送します。 IIS の静的ファイル ハンドラーは使用されず、要求を処理することはできません。
IIS マネージャーで次の手順を実行し、サーバーまたは Web サイト レベルで IIS の静的ファイル ハンドラーを削除します。
- [モジュール] 機能に移動します。
- 一覧の [StaticFileModule] を選択します。
- [アクション] サイドバーで、 [削除] をクリックします。
警告
IIS の静的ファイル ハンドラーが有効になっており、かつ、ASP.NET Core モジュールが正しく構成されていない場合、静的ファイルにサービスが提供されます。 これは、たとえば、web.config ファイルが配置されていない場合などで発生します。
- アプリ プロジェクトの Web ルートの外に、コード ファイル (
.cs
と.cshtml
を含む) を配置します。 これにより、アプリのクライアント側コンテンツとサーバー ベースのコードの間で、論理的な分離が作成されます。 これによって、サーバー側のコードが漏洩するのを防ぎます。
IWebHostEnvironment.WebRootPath を更新して wwwroot の外部のファイルを提供する
IWebHostEnvironment.WebRootPath が wwwroot
以外のフォルダーに設定されている場合:
- 開発環境では、
wwwroot
と更新されたIWebHostEnvironment.WebRootPath
の両方で見つかった静的資産がwwwroot
から提供されます。 - 開発以外のどの環境でも、重複する静的資産は、更新された
IWebHostEnvironment.WebRootPath
フォルダーから提供されます。
空の Web テンプレートを使用して作成された Web アプリについて考えてみましょう。
wwwroot
とwwwroot-custom
にIndex.html
ファイルが含まれる。WebRootPath = "wwwroot-custom"
を設定する、更新された次のProgram.cs
ファイルがある。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();
上記のコードで、/
に要求を行うと:
- 開発環境では
wwwroot/Index.html
が返される - 開発以外のどの環境でも
wwwroot-custom/Index.html
が返される
確実に wwwroot-custom
の資産が返されるようにするには、以下のいずれかの方法を使用します。
wwwroot
内の重複する名前付き資産を削除します。Properties/launchSettings.json
内の"ASPNETCORE_ENVIRONMENT"
を"Development"
以外の任意の値に設定します。プロジェクト ファイルで
<StaticWebAssetsEnabled>false</StaticWebAssetsEnabled>
を設定して、静的 Web 資産を完全に無効にします。 警告: 静的 Web 資産を無効にすると、Razor クラス ライブラリが無効になります。プロジェクト ファイルに次の JSON を追加します。
<ItemGroup> <Content Remove="wwwroot\**" /> </ItemGroup>
次のコードによって、IWebHostEnvironment.WebRootPath
は開発以外の値に更新され、重複するコンテンツが wwwroot
ではなく wwwroot-custom
から返されることが保証されます。
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();
その他のリソース
作成者: Rick Anderson および Kirk Larkin
HTML、CSS、画像、JavaScript などの静的ファイルは、既定では ASP.NET Core アプリにより直接クライアントに提供される資産です。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
静的ファイルの提供
静的ファイルは、プロジェクトの Web ルート ディレクトリ内に格納されています。 既定のディレクトリは {content root}/wwwroot
ですが、UseWebRoot メソッドを使用して変更できます。 詳細については、「コンテンツ ルート」および「Web ルート」を参照してください。
CreateDefaultBuilder メソッドでは、コンテンツのルートが現在のディレクトリに設定されます。
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>();
});
}
上記のコードは、Web アプリ テンプレートを使用して作成されました。
静的ファイルには、Web ルートに対する相対パスを使用してアクセスできます。 たとえば、Web アプリケーション プロジェクト テンプレートでは、wwwroot
フォルダー内に次のいくつかのフォルダーが含まれています。
wwwroot
css
js
lib
wwwroot/images フォルダーを作成し、wwwroot/images/MyImage.jpg
ファイルを追加する場合を考えてみます。 images
フォルダー内のファイルにアクセスするための URI 形式は https://<hostname>/images/<image_file_name>
です。 たとえば、https://localhost:5001/images/MyImage.jpg
Web ルート内のファイルの提供
既定の Web アプリ テンプレートでは、Startup.Configure
内で UseStaticFiles メソッドが呼び出されます。これにより、静的ファイルを提供できるようになります。
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();
});
}
UseStaticFiles
メソッドのパラメーターなしのオーバーロードによって、Web ルート内のファイルが提供可能とマークされます。 次のマークアップは、wwwroot/images/MyImage.jpg
を参照します。
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
上記のコードでは、チルダ文字 ~/
が Web ルートを指します。
Web ルート外のファイルの提供
提供する静的ファイルが Web ルートの外にあるディレクトリ階層について考えます。
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
静的ファイル ミドルウェアを次のように構成すると、要求で red-rose.jpg
ファイルにアクセスできます。
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();
});
}
前述のコードでは、MyStaticFiles ディレクトリ階層は、StaticFiles URI セグメントでパブリックに公開されています。 https://<hostname>/StaticFiles/images/red-rose.jpg
の要求は、red-rose.jpg
ファイルを提供します。
次のマークアップは、MyStaticFiles/images/red-rose.jpg
を参照します。
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
HTTP 応答ヘッダーの設定
StaticFileOptions オブジェクトを使用すると、HTTP 応答ヘッダーを設定できます。 Web ルートから提供される静的ファイルの構成に加えて、次のコードで 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();
});
}
上記のコードでは、max-age (最長有効期間) を 604800 秒 (7 日) に設定しています。
静的ファイルの承認
ASP.NET Core テンプレートでは、UseAuthorization を呼び出す前に UseStaticFiles が呼び出されます。 ほとんどのアプリがこのパターンに従います。 認可ミドルウェアの前に静的ファイル ミドルウェアが呼び出される場合:
- 静的ファイルに対して認可チェックは実行されません。
- 静的ファイル ミドルウェアによって提供される静的ファイル (
wwwroot
下にあるものなど) には、パブリックにアクセスできます。
認可に基づいて静的ファイルを提供するには:
- それらを
wwwroot
の外部に保存します。 UseAuthorization
を呼び出した後に、パスを指定してUseStaticFiles
を呼び出します。- フォールバック認可ポリシーを設定します。
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.
上記のコードでは、フォールバック認可ポリシーによって "すべて" のユーザーを認証することが要求されます。 独自の認可要件を指定する、コントローラー、Razor Pages などのエンドポイントでは、フォールバック認可ポリシーは使用されません。 たとえば、[AllowAnonymous]
や [Authorize(PolicyName="MyPolicy")]
を使用する Razor Pages、コントローラー、またはアクション メソッドでは、フォールバック認可ポリシーではなく適用された認可属性が使用されます。
RequireAuthenticatedUser により、現在のインスタンスに DenyAnonymousAuthorizationRequirement が追加されます。これにより、現在のユーザーが認証されます。
UseAuthentication
の前に既定の静的ファイル ミドルウェア (app.UseStaticFiles();
) が呼び出されるため、wwwroot
下の静的資産にはパブリックにアクセスできます。 MyStaticFiles フォルダー内の静的資産には認証が必要です。 これはサンプル コードで示されています。
認可に基づいてファイルを提供する別の方法:
wwwroot
や静的ファイル ミドルウェアがアクセスできる任意のディレクトリの外にファイルを配置します。- 承認が適用されるアクション メソッドを使用して提供し、FileResult オブジェクトを返します。
[Authorize]
public IActionResult BannerImage()
{
var filePath = Path.Combine(
_env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");
return PhysicalFile(filePath, "image/jpeg");
}
ディレクトリ参照
ディレクトリ参照を使用すると、指定したディレクトリ内のディレクトリを一覧表示できます。
ディレクトリ参照は、セキュリティ上の理由から既定で無効になっています。 詳細については、「静的ファイルのセキュリティに関する注意点」を参照してください。
ディレクトリ参照を有効にするには、次のメソッドを使用します。
Startup.ConfigureServices
の AddDirectoryBrowserStartup.Configure
の UseDirectoryBrowser
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();
});
}
上記のコードでは、URL https://<hostname>/MyImages
が使用され、各ファイルおよびフォルダーへのリンクを含む wwwroot/images フォルダーのディレクトリが参照できるようになります。
既定のドキュメントの提供
既定のページを設定すると、サイトのビジターの開始点になります。 要求 URL にファイルの名前を含めずに wwwroot
から既定のファイルを提供するには、UseDefaultFiles メソッドを呼び出します。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
既定のファイルを提供するには、UseStaticFiles
の前に UseDefaultFiles
が呼び出される必要があります。 UseDefaultFiles
は、ファイルを提供しない URL リライターです。
UseDefaultFiles
を使用すると、wwwroot
内のフォルダーの要求では以下のファイルが検索されます。
default.htm
default.html
index.htm
index.html
一覧で見つかった最初のファイルは、要求にファイル名が含まれていたかのように提供されます。 ブラウザー URL は、要求された URI を反映し続けます。
次のコードによって、既定のファイル名が mydefault.html
に変更されます。
var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
次のコードでは、上記のコードを含めた Startup.Configure
を示します。
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
UseFileServer は、UseStaticFiles
、UseDefaultFiles
、およびオプションとして UseDirectoryBrowser
の機能を兼ね備えています。
app.UseFileServer
を呼び出すと、静的ファイルと既定ファイルが提供できるようになります。 ディレクトリ参照は有効にしません。 次のコードでは、UseFileServer
を含めた Startup.Configure
を示します。
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();
});
}
次のコードによって、静的ファイルの提供、既定ファイル、ディレクトリ参照が有効になります。
app.UseFileServer(enableDirectoryBrowsing: true);
次のコードでは、上記のコードを含めた Startup.Configure
を示します。
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();
});
}
次のディレクトリ階層があるとします。
wwwroot
css
images
js
MyStaticFiles
images
MyImage.jpg
default.html
次のコードによって、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();
});
}
EnableDirectoryBrowsing
プロパティの値が true
であるときは、AddDirectoryBrowser を呼び出す必要があります。
このファイル階層と前述のコードを使用すると、URL は次のように解決されます。
URI | 応答 |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
MyStaticFiles/default.html |
MyStaticFiles ディレクトリに既定の名前のファイルが存在しない場合、https://<hostname>/StaticFiles
によってクリック可能なリンクを含むディレクトリの一覧が返されます。
UseDefaultFiles および UseDirectoryBrowser では、末尾の /
がないターゲット URI から末尾の /
があるターゲット URI へのクライアント側リダイレクトが実行されます。 たとえば、https://<hostname>/StaticFiles
は https://<hostname>/StaticFiles/
になります。 StaticFiles ディレクトリ内の相対 URL は、末尾のスラッシュ (/
) がないと無効です。
FileExtensionContentTypeProvider
FileExtensionContentTypeProvider クラスには、MIME コンテンツ タイプへのファイル拡張子のマッピングを行う Mappings
プロパティが含まれます。 次の例では、いくつかのファイル拡張子が、既知の MIME タイプにマッピングされています。 .rtf 拡張子は置換され、 .mp4 は削除されています。
// 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"
});
次のコードでは、上記のコードを含めた Startup.Configure
を示します。
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();
});
}
「MIME content types」 (MIME コンテンツ タイプ) を参照してください。
非標準のコンテンツ タイプ
静的ファイル ミドルウェアでは、約 400 の既知のファイル コンテンツ タイプが認識されています。 ユーザーがファイルの種類が不明なファイルを要求した場合、静的ファイル ミドルウェアでその要求がパイプラインの次のミドルウェアに渡されます。 ミドルウェアで要求が処理されない場合、404 見つかりません という応答が返されます。 ディレクトリ参照が有効になっている場合、ディレクトリ一覧にファイルへのリンクが表示されます。
次のコードによって、不明なタイプを提供できるようにし、不明なファイルをイメージとしてレンダリングします。
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "image/png"
});
次のコードでは、上記のコードを含めた Startup.Configure
を示します。
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();
});
}
上記のコードでは、不明なコンテンツ タイプ ファイルに対する要求は、イメージとして返されます。
警告
ServeUnknownFileTypes を有効にすると、セキュリティ上リスクとなります。 これは既定では無効で、使用は推奨されていません。 非標準の拡張子のファイルを提供する場合、より安全な代替となるのは、FileExtensionContentTypeProvider です。
複数の場所からファイルを提供する
UseStaticFiles
と UseFileServer
の既定では、wwwroot
をポイントするファイル プロバイダーが作成されます。 UseStaticFiles
および UseFileServer
の追加インスタンスを作成して他のファイル プロバイダーを使用すると、他の場所からファイルを提供することができます。 詳細については、次を参照してください。この GitHub の問題します。
静的ファイルのセキュリティに関する注意点
警告
UseDirectoryBrowser
と UseStaticFiles
では、機密データが漏洩することがあります。 本番では、ディレクトリ参照を無効にすることが、強く推奨されます。 UseStaticFiles
や UseDirectoryBrowser
でどのディレクトリが有効になっているか、慎重にご確認ください。 ディレクトリ全体とそのサブディレクトリが、パブリックにアクセス可能になります。 ファイルは、パブリックに提供するのに適した、<content_root>/wwwroot
などの専用ディレクトリに格納します。 これらのファイルは、MVC ビュー、Razor Pages、構成ファイルなどとは別にします。
UseDirectoryBrowser
とUseStaticFiles
で公開されるコンテンツの URL では、大文字と小文字が区別され、基になるファイル システムの文字制限の影響を受けます。 たとえば、Windows では大文字と小文字が区別されませんが、macOS と Linux では区別されます。IIS でホストされている ASP.NET Core アプリは、ASP.NET Core モジュールを使用して、静的ファイルの要求を含む、すべての要求をアプリに転送します。 IIS の静的ファイル ハンドラーは使用されず、要求を処理することはできません。
IIS マネージャーで次の手順を実行し、サーバーまたは Web サイト レベルで IIS の静的ファイル ハンドラーを削除します。
- [モジュール] 機能に移動します。
- 一覧の [StaticFileModule] を選択します。
- [アクション] サイドバーで、 [削除] をクリックします。
警告
IIS の静的ファイル ハンドラーが有効になっており、かつ、ASP.NET Core モジュールが正しく構成されていない場合、静的ファイルにサービスが提供されます。 これは、たとえば、web.config ファイルが配置されていない場合などで発生します。
- アプリ プロジェクトの Web ルートの外に、コード ファイル (
.cs
と.cshtml
を含む) を配置します。 これにより、アプリのクライアント側コンテンツとサーバー ベースのコードの間で、論理的な分離が作成されます。 これによって、サーバー側のコードが漏洩するのを防ぎます。
その他の技術情報
ASP.NET Core