次の方法で共有


ASP.NET Core の静的ファイル

Note

これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。

Warning

このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、 .NET および .NET Core サポート ポリシーを参照してください。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。

Important

この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。

現在のリリースについては、この記事の .NET 9 バージョンを参照してください。

静的ファイル (静的資産とも呼ばれます) は、動的に生成されない ASP.NET Core アプリのファイルです。 代わりに、HTML、CSS、画像、JavaScript ファイルなど、要求に応じてクライアントに直接提供されます。

この記事のガイダンスに追加または置き換わる静的ファイルのガイダンス Blazor については、「 ASP.NET Core Blazor 静的ファイル」を参照してください。

ASP.NET Core で静的ファイル処理を有効にするには、 MapStaticAssetsを呼び出します。

既定では、静的ファイルはプロジェクトの Web ルート ディレクトリ内に格納されます。 既定のディレクトリは {CONTENT ROOT}/wwwrootで、 {CONTENT ROOT} プレースホルダーはアプリの コンテンツ ルートです。 wwwroot フォルダー内のファイルのみがアドレス指定可能になるため、コードの残りの部分について心配する必要はありません。

サポートされているメディアの種類にマップされた特定のファイル拡張子を持つファイルのみが、静的 Web アセットとして扱われます。

静的 Web アセットはビルド時に検出され、コンテンツ ベースの フィンガープリントを 使用して最適化され、古いファイルが再利用されないようにします。 資産も 圧縮され 、資産の配信時間が短縮されます。

実行時に、検出された静的 Web アセットは、キャッシュヘッダーやコンテンツタイプヘッダーなどのHTTPヘッダーが適用されたエンドポイントとして公開されます。 資産は、ファイルが変更されるか、ブラウザーがそのキャッシュをクリアするまで 1 回提供されます。 ETagLast-Modified、およびContent-Typeヘッダーが設定されます。 ブラウザーでは、アプリの更新後に古い資産を使用できなくなります。

静的資産の配信は エンドポイント ルーティングに基づいているため、承認などの他のエンドポイント対応機能で動作します。 これは、Blazor、Razor Pages、MVC など、すべての UI フレームワークで動作するように設計されています。

静的アセットのマップには、次の利点があります。

  • JavaScript (JS) やスタイルシートを含むが、既に圧縮されているイメージアセットとフォントアセットを除く、アプリ内のすべてのアセットのビルド時圧縮。 Gzip (Content-Encoding: gz) 圧縮は開発中に使用されます。 Gzip 圧縮と Brotli (Content-Encoding: br) 圧縮はどちらも発行時に使用されます。
  • ビルド時に、各ファイルのコンテンツに基づいたSHA-256ハッシュのBase64エンコードされた文字列を使って、すべての資産のフィンガープリントを行います。 これにより、古いファイルがキャッシュされている場合でも、古いバージョンのファイルを再利用できなくなります。 フィンガープリントされた資産はimmutable ディレクティブを使用してキャッシュされるため、ブラウザーは変更されるまで資産を再度要求しません。 immutable ディレクティブをサポートしていないブラウザーの場合は、max-age ディレクティブが追加されます。
    • アセットがフィンガープリントされていない場合でも、ファイルのフィンガープリント ハッシュをETags値として使用して、静的アセットごとにコンテンツ ベースのETagが生成されます。 これにより、コンテンツが変更された場合 (またはファイルが初めてダウンロードされる) 場合にのみ、ブラウザーでファイルがダウンロードされるようになります。
    • 内部的には、フレームワークは物理資産を指紋にマップします。これにより、アプリは次のことができます。
      • RazorのBlazor用にCSSスコープのコンポーネントや、JSで記述されたJSアセットなど、 自動生成されたアセットを検索します。
      • ページの <head> コンテンツにリンク タグを生成して、アセットをプリロードします。

静的アセットのマップでは、縮小やその他のファイル変換の機能は提供されません。 縮小は通常、カスタム コードまたは サード パーティ製ツールによって処理されます。

ASP.NET Core で静的ファイル処理を有効にするには、 UseStaticFilesを呼び出します。

既定では、静的ファイルはプロジェクトの Web ルート ディレクトリ内に格納されます。 既定のディレクトリは {CONTENT ROOT}/wwwrootで、 {CONTENT ROOT} プレースホルダーはアプリの コンテンツ ルートです。 wwwroot フォルダー内のファイルのみがアドレス指定可能になるため、コードの残りの部分について心配する必要はありません。

実行時に、静的 Web アセットは、アセットの変更とコンテンツ タイプ ヘッダーが適用された状態で要求されると、静的ファイル ミドルウェアによって返されます。 ETagLast-Modified、およびContent-Typeヘッダーが設定されます。

静的ファイル ミドルウェアを使用すると、静的ファイルサービスが有効になり、アプリの要求処理パイプラインで UseStaticFiles が呼び出されたときにアプリによって使用されます。 ファイルは、 IWebHostEnvironment.WebRootPath または WebRootFileProvider で指定されたパスから提供されます。既定では Web ルート フォルダー (通常は wwwroot)。

参照先のプロジェクトやパッケージから静的 Web アセットを提供することもできます。

Web ルート ディレクトリを変更する

Web ルートを変更する場合は、 UseWebRoot メソッドを使用します。 詳細については、「 ASP.NET コアの基礎の概要」を参照してください。

プロジェクト ファイル内のwwwroot<Content>を使用してにファイルを発行できないようにします。 次の例では、 wwwroot/local とそのサブディレクトリにコンテンツを発行できないようにします。

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

CreateBuilder メソッドでは、コンテンツのルートが現在のディレクトリに設定されます。

var builder = WebApplication.CreateBuilder(args);

CreateDefaultBuilder メソッドでは、コンテンツのルートが現在のディレクトリに設定されます。

Host.CreateDefaultBuilder(args)

UseHttpsRedirectionの呼び出し後の要求処理パイプラインで、アプリの要求処理パイプラインでMapStaticAssetsを呼び出して、アプリの Web ルートから静的ファイルを提供できるようにします。

app.MapStaticAssets();

UseHttpsRedirectionの呼び出し後の要求処理パイプラインで、アプリの要求処理パイプラインでUseStaticFilesを呼び出して、アプリの Web ルートから静的ファイルを提供できるようにします。

app.UseStaticFiles();

静的ファイルには、Web ルートに対する相対パスを使用してアクセスできます。

wwwroot/images/favicon.pngでイメージにアクセスするには:

  • URL 形式: https://{HOST}/images/{FILE NAME}
    • {HOST} プレースホルダーはホストです。
    • {FILE NAME} プレースホルダーはファイル名です。
    • 絶対 URL: https://localhost:5001/images/favicon.png
    • ルート相対 URL: images/favicon.png

Blazor アプリで、images/favicon.pngアプリのfavicon.png フォルダーからアイコン イメージ (wwwroot/images) を読み込みます。

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

Razor Pages および MVC アプリでは、チルダ文字~は Web ルートを指します。 次の例では、~/images/favicon.pngアプリの favicon.png フォルダーからアイコンイメージ (wwwroot/images) を読み込みます。

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

ミドルウェア パイプラインを短絡化させる

UseStaticFilesの動作である静的資産が一致した後にミドルウェア パイプライン全体が実行されないようにするには、ShortCircuitMapStaticAssetsを呼び出します。 ShortCircuitを呼び出すと、エンドポイントが直ちに実行され、応答が返されるため、他のミドルウェアが静的資産要求に対して実行されなくなります。

app.MapStaticAssets().ShortCircuit();

開発中に静的ファイル キャッシュを制御する

Visual Studio ホット リロード開発テスト中など、開発環境で実行する場合、フレームワークはキャッシュ ヘッダーをオーバーライドして、ブラウザーが静的ファイルをキャッシュできないようにします。 これにより、ファイルが変更されたときに最新バージョンのファイルが使用され、古いコンテンツの問題を回避できます。 運用環境では、正しいキャッシュ ヘッダーが設定され、ブラウザーは静的資産を想定どおりにキャッシュできます。

この動作を無効にするには、EnableStaticAssetsDevelopmentCachingを開発環境のアプリ設定ファイル (true) でappsettings.Development.jsonに設定します。

Development以外の環境の静的ファイル

アプリをローカルで実行する場合、静的 Web アセットは開発環境でのみ有効になります。 ローカルの開発中やテスト中 (ステージング環境など) に対して開発以外の環境で静的ファイルを有効にするには、UseStaticWebAssetsWebApplicationBuilderを呼び出します。

Warning

UseStaticWebAssetsを呼び出して、正確な環境を設定し、本番環境で機能を有効にすることを防ぎます。これは、プロジェクトとは異なるディスク上の別の場所からファイルを処理するためです。 このセクションの例では、 IsStagingを使用してステージング環境を確認します。

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

IWebHostEnvironment.WebRootPath を使用して Web ルート ディレクトリの外部でファイルを提供する

IWebHostEnvironment.WebRootPathwwwroot 以外のフォルダーに設定されている場合、次の既定の動作が表示されます。

  • 開発環境では、同じ名前のアセットがwwwrootwwwrootに割り当てられた別のフォルダーの両方にある場合、静的アセットはWebRootPathから提供されます。
  • 開発以外の環境では、重複する静的資産が WebRootPath フォルダーから提供されます。

空の Web テンプレートから作成された Web アプリについて考えてみましょう。

  • Index.htmlwwwrootwwwroot-custom ファイルが含まれる。
  • Program ファイルが更新され、WebRootPath = "wwwroot-custom"が設定されます。
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    Args = args,
    WebRootPath = "wwwroot-custom"
});

既定では、/への要求の場合:

  • 開発環境では、 wwwroot/Index.html が返されます。
  • 開発以外の環境では、 wwwroot-custom/Index.html が返されます。

wwwroot-customの資産が常に返されるようにするには、次のいずれかの方法を使用します。

  • wwwrootで重複する名前付き資産を削除します。

  • ASPNETCORE_ENVIRONMENT 内の Properties/launchSettings.jsonDevelopment 以外の任意の値に設定します。

  • アプリのプロジェクト ファイルで<StaticWebAssetsEnabled>するようにfalseを設定して、静的 Web アセットを無効にします。 警告:静的 Web アセットを無効にすると、クラス ライブラリRazor無効になります

  • 次の XML をプロジェクト ファイルに追加します。

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

次のコードは、WebRootPathを開発以外の値 (Staging) に更新し、wwwroot-customではなくwwwrootから重複するコンテンツが返されるようにします。

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

静的ファイル ミドルウェア

静的ファイル ミドルウェアを使用すると、静的ファイルを特定の静的ファイル シナリオで提供できます。通常は、静的資産のマップ エンドポイント ルーティング規則 (MapStaticAssets) に加えて機能します。

静的ファイル ミドルウェアは、アプリの要求処理パイプラインで UseStaticFiles が呼び出されたときに要求処理に含まれます。通常は、静的資産のマップ エンドポイント規則 (MapStaticAssets) が追加された後です。

マップ静的資産エンドポイント規則は、.NET 9 以降を対象とするアプリで使用されます。 静的ファイル ミドルウェアは、.NET 9 より前のバージョンの .NET を対象とするアプリで使用する必要があります。

静的ファイル ミドルウェアは静的ファイルを提供しますが、静的資産のマップ エンドポイント規則と同じレベルの最適化を提供しません。 静的ファイル ミドルウェアのみに依存している場合、Map Static Assets エンドポイント規則のビルド時の圧縮とフィンガープリント機能は使用できません。

エンドポイント規則は、アプリが実行時に認識している資産を提供するために最適化されています。 アプリがディスクや埋め込みリソースなどの他の場所の資産を提供する場合は、静的ファイル ミドルウェアを使用する必要があります。

この記事で取り上げる次の機能は、静的ファイル ミドルウェアではサポートされていますが、Map Static Assets エンドポイント規則ではサポートされていません。

UseStaticFiles を使用して Web ルート ディレクトリの外部でファイルを提供する

という名前のフォルダーにアプリの ExtraStaticFilesの外部に存在する静的ファイルを含む次のディレクトリ階層について考えてみましょう。

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

要求は、静的ファイル ミドルウェアの新しいインスタンスを構成することで、 red-rose.jpg にアクセスできます。

次の API の名前空間:

using Microsoft.Extensions.FileProviders;

MapStaticAssets (.NET 9 以降) または UseStaticFiles (.NET 8 以前) への既存の呼び出し後の要求処理パイプラインで、

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

前のコードでは、 ExtraStaticFiles ディレクトリ階層は、 static-files URL セグメントを介してパブリックに公開されています。 https://{HOST}/StaticFiles/images/red-rose.jpg への要求では、ホストである{HOST} プレースホルダーがred-rose.jpg ファイルを提供します。

次のマークアップは、ExtraStaticFiles/images/red-rose.jpg を参照します。

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

前の例では、Razor ページおよび src="~/StaticFiles/images/red-rose.jpg" MVC ビュー (Razor) でチルダスラッシュ表記がサポートされていますが、Blazor アプリのコンポーネントではサポートされていません。

複数の場所からファイルを提供する

このセクションのガイダンスは、 Razor Pages と MVC アプリに適用されます。 Blazor Web App に適用されるガイダンスについては、「ASP.NET Core Blazor 静的ファイル」をご覧ください。

会社のロゴを表示する次のマークアップについて考えてみましょう。

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

開発者は 、イメージ タグ ヘルパー を使用してバージョンを追加し、カスタムの場所 ( ExtraStaticFiles という名前のフォルダー) からファイルを提供する予定です。

次の例では、 MapStaticAssets を呼び出して wwwroot からファイルを提供し、 UseStaticFiles を呼び出して、 ExtraStaticFilesからファイルを提供します。

MapStaticAssets (.NET 9 以降) または UseStaticFiles (.NET 8 以前) への既存の呼び出し後の要求処理パイプラインで、

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

次の例では、 UseStaticFiles を 2 回呼び出して、 wwwrootExtraStaticFilesの両方のファイルを処理します。

UseStaticFilesへの既存の呼び出しの後の要求処理パイプラインで、次の手順を実行します。

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

上記のコードを使用して、 ExtraStaticFiles/logo.png ファイルが表示されます。 ただし、タグ ヘルパーは フォルダーを含むように更新されていないAppendVersionに依存するため、WebRootFileProvider (ExtraStaticFiles) は適用されません。

次のコードは、WebRootFileProviderを使用してExtraStaticFiles フォルダーを含むようにCompositeFileProviderを更新します。 これにより、イメージ タグ ヘルパーは、 ExtraStaticFiles フォルダー内のイメージにバージョンを適用できます。

次の API の名前空間:

using Microsoft.Extensions.FileProviders;

MapStaticAssets (.NET 9 以降) またはUseStaticFiles (.NET 8 以前) の既存の呼び出し前の要求処理パイプラインで、

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

var compositeProvider = new CompositeFileProvider(webRootProvider, newPathProvider);

app.Environment.WebRootFileProvider = compositeProvider;

UseStaticFilesUseFileServer の既定では、wwwroot をポイントするファイル プロバイダーが作成されます。 UseStaticFiles および UseFileServer の追加インスタンスを作成して他のファイル プロバイダーを使用すると、他の場所からファイルを提供することができます。 詳細については、「 wwwroot に対して UseFileServer と共に UseStaticFiles も必要であること (dotnet/AspNetCore.Docs #15578)」を参照してください。

HTTP 応答ヘッダーの設定

StaticFileOptionsを使用して HTTP 応答ヘッダーを設定します。 静的ファイルを提供するように静的ファイル ミドルウェアを構成するだけでなく、次のコードではCache-Control ヘッダーを 604,800 秒 (1 週間) に設定します。

次の API の名前空間:

using Microsoft.AspNetCore.Http;

MapStaticAssets (.NET 9 以降) または UseStaticFiles (.NET 8 以前) への既存の呼び出し後の要求処理パイプラインで、

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

資産の大規模なコレクション

約 1,000 以上の資産と見なされる大量の資産を扱う場合は、バンドルを使用して、アプリによって提供される最終的なアセットの数を減らすか、 MapStaticAssetsUseStaticFilesを組み合わせることをお勧めします。

MapStaticAssets 圧縮、キャッシュ、フィンガープリントをサポートするために、リソースのビルド プロセス中にキャプチャされた事前計算済みメタデータを熱心に読み込みます。 これらの機能は、アプリによるメモリ使用量の向上を犠牲にしています。 頻繁にアクセスされる資産の場合、通常はコストの価値があります。 頻繁にアクセスされない資産の場合、トレードオフはコストに見合わない可能性があります。

バンドルを使用しない場合は、 MapStaticAssetsUseStaticFilesを組み合わせることをお勧めします。 次の例は、このアプローチを示しています。

プロジェクト ファイル (.csproj) では、 StaticWebAssetEndpointExclusionPattern MSBuild プロパティを使用して、 MapStaticAssetsの最終的なマニフェストからエンドポイントをフィルター処理します。 除外されたファイルは UseStaticFiles によって提供され、圧縮、キャッシュ、フィンガープリントの恩恵を受けられません。

StaticWebAssetEndpointExclusionPatternの値を設定するときは、フレームワークの既定の除外パターンを保持するために$(StaticWebAssetEndpointExclusionPattern)を保持します。 セミコロンで区切られたリストにパターンを追加します。

次の例では、除外パターンによって、アイコンの仮想バッチを表す lib/icons フォルダー内の静的ファイルが除外されます。

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

app.UseHttpsRedirection(); ファイルでの HTTPS リダイレクト ミドルウェア (Program) の処理後:

  • UseStaticFilesを呼び出して、除外されたファイル (lib/icons/**) と、MapStaticAssetsでカバーされていないその他のファイルを処理します。
  • MapStaticAssets後にUseStaticFilesを呼び出して、重要なアプリケーション ファイル (CSS、JS、画像) を処理します。
app.UseStaticFiles();

app.UseAuthorization();

app.MapStaticAssets();

静的ファイルの承認

アプリが フォールバック承認ポリシーを採用する場合、承認ミドルウェアが要求を処理した後の静的ファイルの要求を含め、承認ポリシーを明示的に指定しないすべての要求に承認が必要です。 静的ファイルのエンドポイント ビルダーに AllowAnonymousAttribute を適用して、静的ファイルへの匿名アクセスを許可します。

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

アプリが フォールバック承認ポリシーを採用する場合、承認ミドルウェアが要求を処理した後の静的ファイルの要求を含め、承認ポリシーを明示的に指定しないすべての要求に承認が必要です。 ASP.NET Core テンプレートでは、UseStaticFilesを呼び出す前にUseAuthorizationを呼び出すことによって、静的ファイルへの匿名アクセスを許可します。 ほとんどのアプリがこのパターンに従います。 認可ミドルウェアの前に静的ファイル ミドルウェアが呼び出される場合:

  • 静的ファイルに対して認可チェックは実行されません。
  • 静的ファイル ミドルウェアによって提供される静的ファイル、例えばウェブルート(通常、wwwroot)は、一般にアクセス可能です。

認可に基づいて静的ファイルを提供するには:

  • アプリで、認証されたユーザーを要求するように フォールバック承認ポリシー が設定されていることを確認します。
  • アプリの Web ルートの外部に静的ファイルを格納します。
  • UseAuthorizationを呼び出した後、UseStaticFilesを呼び出し、Web ルートの外部にある静的ファイル フォルダーへのパスを指定します。

次の API の名前空間:

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

サービスの登録:

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

UseAuthorizationの呼び出し後の要求処理パイプラインで、次の手順を実行します。

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

次の API の名前空間:

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

Startup.ConfigureServicesの場合:

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

Startup.Configure後のUseAuthorization呼び出しでは、

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

前のコードでは、フォールバック承認ポリシーには認証済みユーザーが必要です。 コントローラーや Razor ページなど、独自の承認要件を指定するエンドポイントでは、フォールバック承認ポリシーは使用されません。 たとえば、Razor や [AllowAnonymous] を使用する [Authorize(PolicyName="MyPolicy")] Pages、コントローラー、またはアクション メソッドでは、フォールバック認可ポリシーではなく適用された認可属性が使用されます。

RequireAuthenticatedUser により、現在のインスタンスに DenyAnonymousAuthorizationRequirement が追加されます。これにより、現在のユーザーが認証されます。

既定の静的ファイル ミドルウェア (UseStaticFiles) は UseAuthorization前に呼び出されるため、アプリの Web ルートに格納されている静的資産にはパブリックにアクセスできます。 SecureStaticFiles フォルダー内の静的資産には認証が必要です。

認可に基づいてファイルを提供する別の方法:

  • Web ルートの外部にあるファイルと、静的ファイル ミドルウェアからアクセスできる任意のディレクトリを格納します。
  • 承認が適用されるアクション メソッドを介してファイルを提供し、 FileResult オブジェクトを返します。

Razor ページから (Pages/BannerImage.cshtml.cs):

public class BannerImageModel : PageModel
{
    private readonly IWebHostEnvironment _env;

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

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

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

コントローラーから (Controllers/HomeController.cs):

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

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

上記の方法では、ファイルごとにページまたはエンドポイントが必要です。

次のルート エンドポイントの例では、認証されたユーザーのファイルが返されます。

Program ファイルで次の操作を行います。

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

...

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

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

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

次のルート エンドポイントの例では、管理者ロール ("admin") の認証済みユーザーのファイルをアップロードします。

Program ファイルで次の操作を行います。

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

...

// IFormFile uses memory buffer for uploading. For handling large 
// files, use streaming instead. See the *File uploads* article
// in the ASP.NET Core documentation:
// https://learn.microsoft.com/aspnet/core/mvc/models/file-uploads
app.MapPost("/files", async (IFormFile file, LinkGenerator linker, 
    HttpContext context) =>
{
    // Don't rely on the value in 'file.FileName', as it's only metadata that can 
    // be manipulated by the end-user. Consider the 'Utilities.IsFileValid' method 
    // that takes an 'IFormFile' and validates its signature within the 
    // 'AllowedFileSignatures'.

    var fileSaveName = Guid.NewGuid().ToString("N") + 
        Path.GetExtension(file.FileName);
    await SaveFileWithCustomFileName(file, fileSaveName);

    context.Response.Headers.Append("Location", linker.GetPathByName(context, 
        "GetFileByName", new { fileName = fileSaveName}));

    return TypedResults.Ok("File Uploaded Successfully!");
})
.RequireAuthorization("AdminsOnly");

Startup.ConfigureServicesの場合:

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

Startup.Configureの場合:

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

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

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

次のコードは、管理者ロール ("admin") の認証済みユーザーのファイルをアップロードします。

Startup.ConfigureServicesの場合:

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

Startup.Configureの場合:

// IFormFile uses memory buffer for uploading. For handling large 
// files, use streaming instead. See the *File uploads* article
// in the ASP.NET Core documentation:
// https://learn.microsoft.com/aspnet/core/mvc/models/file-uploads
app.MapPost("/files", async (IFormFile file, LinkGenerator linker, 
    HttpContext context) =>
{
    // Don't rely on the value in 'file.FileName', as it's only metadata that can 
    // be manipulated by the end-user. Consider the 'Utilities.IsFileValid' method 
    // that takes an 'IFormFile' and validates its signature within the 
    // 'AllowedFileSignatures'.

    var fileSaveName = Guid.NewGuid().ToString("N") + 
        Path.GetExtension(file.FileName);
    await SaveFileWithCustomFileName(file, fileSaveName);

    context.Response.Headers.Append("Location", linker.GetPathByName(context, 
        "GetFileByName", new { fileName = fileSaveName}));

    return TypedResults.Ok("File Uploaded Successfully!");
})
.RequireAuthorization("AdminsOnly");

ディレクトリの参照

ディレクトリ参照を使用すると、指定したディレクトリ内のディレクトリを一覧表示できます。

ディレクトリ参照は、セキュリティ上の理由から既定で無効になっています。 詳細については、「静的ファイルのセキュリティに関する注意点」を参照してください。

次の API を使用してディレクトリ参照を有効にします。

次に例を示します。

  • アプリのルートにある images フォルダーには、ディレクトリ参照用のイメージが格納されます。
  • イメージを参照する要求パスは /DirectoryImages
  • UseStaticFilesを呼び出し、FileProviderStaticFileOptionsを設定すると、個々のファイルへのブラウザー リンクを表示できます。

次の API の名前空間:

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

サービスの登録:

builder.Services.AddDirectoryBrowser();

MapStaticAssets (.NET 9 以降) または UseStaticFiles (.NET 8 以前) への既存の呼び出し後の要求処理パイプラインで、

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

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

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

次の API の名前空間:

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

Startup.ConfigureServicesの場合:

services.AddDirectoryBrowser();

Startup.Configureへの既存の呼び出しの後でのUseStaticFiles:

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

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

上記のコードでは、URL wwwroot/imagesを使用して、各ファイルとフォルダーへのリンクを使用して、https://{HOST}/DirectoryImages フォルダーをディレクトリで参照できます。ここで、{HOST} プレースホルダーはホストです。

AddDirectoryBrowser は、 HtmlEncoderを含む、ディレクトリ参照ミドルウェアに必要なサービスを追加します。 これらのサービスは、 AddRazorPagesなどの他の呼び出しによって追加される場合がありますが、サービスが確実に追加されるように AddDirectoryBrowser を呼び出することをお勧めします。

既定のドキュメントの提供

既定のページを設定すると、サイトのビジターの開始点になります。 要求 URL にファイル名を含める必要なく、 wwwroot から既定のファイルを提供するには、 UseDefaultFiles メソッドを呼び出します。

UseDefaultFiles は、ファイルを提供しない URL リライターです。 MapStaticAssets (.NET 9 以降) または UseStaticFiles (.NET 8 以前) への既存の呼び出しの前の要求処理パイプラインで、

app.UseDefaultFiles();

UseDefaultFiles を使用すると、wwwroot 内のフォルダーの要求では以下のファイルが検索されます。

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

一覧で見つかった最初のファイルは、要求にファイル名が含まれていたかのように提供されます。 ブラウザー URL は、要求された URI を反映し続けます。

次のコードによって、既定のファイル名が default-document.html に変更されます。

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

静的ファイル、既定のドキュメント、およびディレクトリ参照を結合する

UseFileServer は、UseStaticFilesUseDefaultFiles、およびオプションとして UseDirectoryBrowser の機能を兼ね備えています。

MapStaticAssets (.NET 9 以降) または UseStaticFiles (.NET 8 以前) への既存の呼び出し後の要求処理パイプラインで、UseFileServerを呼び出して静的ファイルと既定のファイルの提供を有効にします。

app.UseFileServer();

前の例では、ディレクトリ参照は有効になっていません。

次のコードでは、静的ファイル、既定のファイル、およびディレクトリ参照の提供を有効にします。

サービスの登録:

builder.Services.AddDirectoryBrowser();

UseStaticFilesへの既存の呼び出しの後の要求処理パイプラインで、次の手順を実行します。

app.UseFileServer(enableDirectoryBrowsing: true);

Startup.ConfigureServicesの場合:

services.AddDirectoryBrowser();

Startup.Configureへの既存の呼び出しの後でのUseStaticFiles:

app.UseFileServer(enableDirectoryBrowsing: true);

ホスト アドレス (/) の場合、 UseFileServer は既定の Razor ページ (Pages/Index.cshtml) または既定の MVC ビュー (Home/Index.cshtml) の前に既定の HTML ドキュメントを返します。

次のディレクトリ階層があるとします。

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

次のコードでは、静的ファイル、既定のファイル、および ExtraStaticFilesのディレクトリ参照の提供を有効にします。

次の API の名前空間:

using Microsoft.Extensions.FileProviders;

サービスの登録:

builder.Services.AddDirectoryBrowser();

UseStaticFilesへの既存の呼び出しの後の要求処理パイプラインで、次の手順を実行します。

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

次の API の名前空間:

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

Startup.ConfigureServicesの場合:

services.AddDirectoryBrowser();

Startup.Configureへの既存の呼び出しの後でのUseStaticFiles:

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

AddDirectoryBrowser プロパティの値が EnableDirectoryBrowsing であるときは、true を呼び出す必要があります。

上記のファイル階層とコードを使用して、URL は次の表に示すように解決されます ( {HOST} プレースホルダーはホストです)。

URI 応答ファイル
https://{HOST}/static-files/images/logo.png ExtraStaticFiles/images/logo.png
https://{HOST}/static-files ExtraStaticFiles/default.html

ExtraStaticFiles ディレクトリに既定の名前付きファイルが存在しない場合、https://{HOST}/static-filesはクリック可能なリンクを含むディレクトリリストを返します。ここで、{HOST} プレースホルダーはホストです。

UseDefaultFiles および UseDirectoryBrowser では、末尾の / がないターゲット URI から末尾の / があるターゲット URI へのクライアント側リダイレクトが実行されます。 たとえば、 https://{HOST}/static-files (末尾の /なし) から https://{HOST}/static-files/ (末尾の /を含む) までです。 ExtraStaticFiles ディレクトリ内の相対 URL は、/RedirectToAppendTrailingSlash オプションを使用しない限り、末尾のスラッシュ (DefaultFilesOptions) なしでは無効です。

ファイル拡張子を MIME の種類にマップする

Note

Blazor アプリに適用されるガイダンスについては、ASP.NET Core Blazor静的ファイルに関するページを参照してください。

FileExtensionContentTypeProvider.Mappingsを使用して、MIME コンテンツ タイプ マッピングにファイル拡張子を追加または変更します。 次の例では、いくつかのファイル拡張子が既知の MIME の種類にマップされています。 .rtf拡張機能が置き換えられ、.mp4が削除されます。

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

...

// Set up custom content types - associating file extension to MIME type
var provider = new FileExtensionContentTypeProvider();
// Add new mappings
provider.Mappings[".myapp"] = "application/x-msdownload";
provider.Mappings[".htm3"] = "text/html";
provider.Mappings[".image"] = "image/png";
// Replace an existing mapping
provider.Mappings[".rtf"] = "application/x-msdownload";
// Remove MP4 videos
provider.Mappings.Remove(".mp4");

app.UseStaticFiles(new StaticFileOptions
{
    ContentTypeProvider = provider
});

いくつかの静的ファイル オプションを構成する場合は、 StaticFileOptionsを使用してプロバイダーを設定することもできます。

var provider = new FileExtensionContentTypeProvider();

...

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

app.UseStaticFiles();

Startup.Configureの場合:

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

...

// Set up custom content types - associating file extension to MIME type
var provider = new FileExtensionContentTypeProvider();
// Add new mappings
provider.Mappings[".myapp"] = "application/x-msdownload";
provider.Mappings[".htm3"] = "text/html";
provider.Mappings[".image"] = "image/png";
// Replace an existing mapping
provider.Mappings[".rtf"] = "application/x-msdownload";
// Remove MP4 videos
provider.Mappings.Remove(".mp4");

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

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

詳細については、「 MIME コンテンツ タイプ」を参照してください。

非標準のコンテンツ タイプ

静的ファイル ミドルウェアでは、約 400 の既知のファイル コンテンツ タイプが認識されています。 ユーザーがファイルの種類が不明なファイルを要求した場合、静的ファイル ミドルウェアでその要求がパイプラインの次のミドルウェアに渡されます。 ミドルウェアで要求が処理されない場合、404 見つかりません という応答が返されます。 ディレクトリ参照が有効になっている場合、ディレクトリ一覧にファイルへのリンクが表示されます。

次のコードでは、不明なコンテンツ タイプを提供し、不明なファイルをイメージとしてレンダリングします。

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

上記のコードでは、不明なコンテンツ タイプ ファイルに対する要求は、イメージとして返されます。

Warning

ServeUnknownFileTypes を有効にすると、セキュリティ上リスクとなります。 これは既定では無効で、使用は推奨されていません。 ファイル拡張子を MIME の種類にマップ すると、標準以外の拡張子でファイルを提供するより安全な代替手段が提供されます。

カスタム静的ファイル マニフェストを指定する

staticAssetsManifestPathnullされている場合は、マニフェストの検索にIHostEnvironment.ApplicationNameが使用されます。 または、マニフェスト ファイルへの完全なパスを指定します。 相対パスが使用されている場合、フレームワークは AppContext.BaseDirectory内のファイルを検索します。

静的ファイルのセキュリティに関する注意点

Warning

UseDirectoryBrowserUseStaticFiles では、機密データが漏洩することがあります。 本番では、ディレクトリ参照を無効にすることが、強く推奨されます。 UseStaticFilesUseDirectoryBrowser でどのディレクトリが有効になっているか、慎重にご確認ください。 ディレクトリ全体とそのサブディレクトリが、パブリックにアクセス可能になります。 ファイルは、パブリックに提供するのに適した、<content_root>/wwwroot などの専用ディレクトリに格納します。 これらのファイルは、MVC ビュー、Razor Pages、構成ファイルなどとは別にします。

  • UseDirectoryBrowserUseStaticFiles で公開されるコンテンツの URL では、大文字と小文字が区別され、基になるファイル システムの文字制限の影響を受けます。 たとえば、Windows では大文字と小文字が区別されませんが、macOS と Linux では区別されます。

  • IIS でホストされている ASP.NET Core アプリは、ASP.NET Core モジュールを使用して、静的ファイルの要求を含む、すべての要求をアプリに転送します。 IIS の静的ファイル ハンドラーは使用されず、要求を処理することはできません。

  • IIS マネージャーで次の手順を実行し、サーバーまたは Web サイト レベルで IIS の静的ファイル ハンドラーを削除します。

    1. [モジュール] 機能に移動します。
    2. 一覧の [StaticFileModule] を選択します。
    3. [アクション] サイドバーで、 [削除] をクリックします。

Warning

IIS の静的ファイル ハンドラーが有効になっており、かつ、ASP.NET Core モジュールが正しく構成されていない場合、静的ファイルにサービスが提供されます。 これは、たとえば、 web.config ファイルがデプロイされていない場合に発生します。

  • アプリ プロジェクトの .csの外に、コード ファイル ( .cshtml を含む) を配置します。 これにより、アプリのクライアント側コンテンツとサーバー ベースのコードの間で、論理的な分離が作成されます。 これによって、サーバー側のコードが漏洩するのを防ぎます。

MSBuild プロパティ

次の表に、静的ファイル MSBuild のプロパティとメタデータの説明を示します。

プロパティ Description
EnableDefaultCompressedItems 既定の圧縮インクルード/除外パターンを有効にします。
CompressionIncludePatterns 圧縮に含めるファイル パターンのセミコロン区切りの一覧。
CompressionExcludePatterns 圧縮から除外するファイル パターンのセミコロン区切りの一覧。
EnableDefaultCompressionFormats 既定の圧縮形式 (Gzip と Brotli) を有効にします。
BuildCompressionFormats ビルド中に使用する圧縮形式。
PublishCompressionFormats 発行時に使用する圧縮形式。
DisableBuildCompression ビルド中の圧縮を無効にします。
CompressDiscoveredAssetsDuringBuild ビルド中に検出された資産を圧縮します。
BrotliCompressionLevel Brotli アルゴリズムの圧縮レベル。
StaticWebAssetBuildCompressAllAssets ビルド中に検出または計算された資産だけでなく、ビルド中にすべての資産を圧縮します。
StaticWebAssetPublishCompressAllAssets ビルド中に検出または計算された資産だけでなく、発行中にすべての資産を圧縮します。
プロパティ Description
StaticWebAssetBasePath ライブラリ内のすべての資産のベース URL パス。
StaticWebAssetsFingerprintContent キャッシュ の無効化に対するコンテンツフィンガープリントを有効にします。
StaticWebAssetFingerprintingEnabled 静的 Web 資産のフィンガープリント機能を有効にします。
StaticWebAssetsCacheDefineStaticWebAssetsEnabled 静的 Web アセット定義のキャッシュを有効にします。
StaticWebAssetEndpointExclusionPattern エンドポイントを除外するためのパターン。
品目グループ Description メタデータ
StaticWebAssetContentTypeMapping エンドポイントのコンテンツ タイプとキャッシュ ヘッダーにファイル パターンをマップします。 PatternCache
StaticWebAssetFingerprintPattern キャッシュ の無効化のために静的 Web 資産に指紋を適用するためのパターンを定義します。 PatternExpression

メタデータの説明:

  • Pattern: ファイルの照合に使用される glob パターン。 StaticWebAssetContentTypeMappingの場合、ファイルと一致してコンテンツ タイプ (JavaScript ファイルの*.jsなど) を決定します。 StaticWebAssetFingerprintPatternの場合、特殊なフィンガープリント処理を必要とするマルチ拡張ファイル (*.lib.module.js など) を識別します。

  • Cache: 一致するコンテンツ タイプの Cache-Control ヘッダー値を指定します。 これにより、ブラウザーのキャッシュ動作 (メディア ファイルの max-age=3600, must-revalidate など) が制御されます。

  • Expression: フィンガープリントをファイル名に挿入する方法を定義します。 既定値は #[.{FINGERPRINT}] で、指紋 (プレースホルダー{FINGERPRINT} ) が拡張機能の前に挿入されます。

次の例では、フィンガープリントされていないエンドポイントに使用する.bmp ヘッダーを表すimage/bmp プレースホルダーを使用して、ビットマップ ファイル パターン ({CACHE HEADER}) をCache-Controlコンテンツ タイプにマップします。

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

ランタイム構成オプション

次の表では、ランタイム構成オプションについて説明します。

構成キー Description
ReloadStaticAssetsAtRuntime 静的アセットの開発時ホット リロードを有効にします。ビルド時マニフェスト のバージョンではなく、変更された Web ルート (wwwroot) ファイルを処理します ( ETagを再計算し、必要に応じて再圧縮します)。 明示的に設定しない限り、ビルド マニフェストを提供する場合にのみ、既定で有効になります。
DisableStaticAssetNotFoundRuntimeFallback trueすると、ビルド マニフェストに存在しない新しく追加されたファイルを処理するフォールバック エンドポイントが抑制されます。 falseの存在または不在の場合、GET/HEADによるfile-exists-checked {**path}フォールバックが警告をログに記録し、計算されたETagでファイルを処理します。
EnableStaticAssetsDevelopmentCaching trueすると、資産記述子の元のCache-Control ヘッダーが保持されます。 falseがある場合、または存在しない場合は、開発中にクライアントキャッシュを積極的に回避するために、Cache-Controlヘッダーをno-cacheに書き換えます。
EnableStaticAssetsDevelopmentIntegrity trueすると、資産記述子の整合性プロパティが保持されます。 falseまたは存在しない場合は、開発中にファイルが変更されたときに不一致を防ぐために、整合性プロパティを削除します。

その他のリソース