LoginSignup
3
1

More than 5 years have passed since last update.

Working with Static Files - 日本語意訳

Last updated at Posted at 2017-04-08

ASP.NET Core での 静的ファイルの扱い 概要

静的ファイルの提供

静的ファイルは通常 web root<content-root>/wwwroot)フォルダに配置されます。詳細については ASP.NET Core 入門 の「Content root と Web root」を参照してください。開発中は web root が見つかるように、Content root をカレントディレクトリに指定するのが一般的です。

C#
public static void Main(string[] args)
{
    var host = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<Startup>()
        .Build();

    host.Run();
}

静的ファイルは、web root 配下の任意のフォルダに配置し、そのルートからの相対パスでアクセスすることができます。例えば、Visual Studio でデフォルト Web アプリケーションプロジェクトを作成すると、wwwroot フォルダ配下に cssimagesjs といったフォルダが作成されます。images サブフォルダ内の画像にアクセスするための URI は以下のようになります:

  • http://<app>/images/<imageFileName>
  • http://localhost:9189/images/banner3.svg

静的ファイルを提供するためには、Middleware を構成して、静的ファイルをパイプラインに追加しなくてはなりません。Nuget で Microsoft.AspNetCore.StaticFiles パッケージの参照をプロジェクトに追加し、Startup.Configure 内で
UseStaticFiles 拡張メソッドを実行することで、Static file Middleware を構成することができます:

C#
public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles();
}

app.UseStaticFiles(); は、web root(デフォルトで wwwroot)内にある静的ファイルを提供可能にします。後ほど、UseStaticFiles メソッドを使って他のディレクトリコンテンツを提供可能にする方法を示します。

[!注意]
web root のデフォルトは wwwroot ディレクトリですが、UseWebRoot メソッドを使用して web root ディレクトリを変更することができます。

提供したい静的ファイルが web root の外部にあるようなプロジェクト階層があるとします。例えば:

  • wwwroot
    • css
    • images
    • ...
  • MyStaticFiles
    • test.png

test.png へアクセスするためには、Static files Middleware を次のように構成します:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"MyStaticFiles")),
        RequestPath = new PathString("/StaticFiles")
    });
}

http://<app>/StaticFiles/test.png へリクエストすることで test.png ファイルが提供されます。

StaticFileOptions() はレスポンスヘッダーを設定できます。例えば、以下のコードは wwwroot フォルダから静的ファイルを提供するよう設定し、Cache-Control ヘッダーを設定して10分間(600秒)キャッシュ可能にしています:

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

Response headers showing the Cache-Control header has been added

静的ファイルの認可

Static file Middleware は認可のチェックを行いませんwwwroot 配下のファイルを含む、Static file Middleware によって提供されるファイルは全て公開されます。認可に基づいてファイルを提供するには:

  • wwwroot や Static file Middleware がアクセスできるディレクトリの外部にファイルを配置し、かつ

  • コントローラーアクションを通してファイルを提供するようにし、認可が適用される FileResult を返すようにします。

ディレクトリ参照を有効にする

ディレクトリ参照は、ユーザーに指定されたディレクトリ内のディレクトリとファイルのリストを参照可能にします。セキュリティの理由(検討事項を参照)からディレクトリ参照はデフォルトで無効にされています。ディレクトリ参照を有効にするには Startup.Configureメソッド内で UseDirectoryBrowser 拡張メソッドを実行してください:

C#
public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot", "images")),
        RequestPath = new PathString("/MyImages")
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot", "images")),
        RequestPath = new PathString("/MyImages")
    });
}

また、Startup.ConfigureServices メソッド内で AddDirectoryBrowser 拡張メソッドを実行して必要な Service を追加してください:

C#
public void ConfigureServices(IServiceCollection services)
{
    services.AddDirectoryBrowser();
}

上記のコードは wwwroot/images フォルダへのディレクトリ参照を許可します。URL http://<app>/MyImages で参照でき、各ファイルやフォルダへのリンクは以下のとおりです:

directory browsing

ディレクトリ参照を有効にした際のセキュリティリスクについては 検討事項 を参照してください。

2つの app.UseStaticFiles の呼び出しに注目してください。1つ目は wwwroot フォルダ内の CSS、images、JavaScript ファイルを提供し、2つ目は URL http://<app>/MyImages で wwwroot/images フォルダへのディレクトリ参照を許可します:

C#
public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot", "images")),
        RequestPath = new PathString("/MyImages")
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot", "images")),
        RequestPath = new PathString("/MyImages")
    });
}

デフォルトドキュメントの提供

デフォルトのホームページを設定することで、サイト訪問者にサイトを開始する場所を提供します。ユーザーが URI を完全指定しなくともデフォルトページが提供されるようにするには、次のように Startup.Configure 内で UseDefaultFiles 拡張メソッドを実行してください。

C#
public void Configure(IApplicationBuilder app)
{
    app.UseDefaultFiles();
    app.UseStaticFiles();
}

[!注意]
デフォルトファイルを提供するためには、UseDefaultFiles メソッドは UseStaticFiles メソッドの前に実行しなければなりません。UseDefaultFiles は URL 書き換えであり、実際にファイルを提供しているわけではありません。ファイルを提供するためには、Static file Middleware (UseStaticFiles) を有効化しなければなりません。

UseDefaultFiles を使用すると、フォルダへのリクエストが行われると次のファイルが検索されます:

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

まるでリクエストが完全指定された URI であるかのように、リストから見つかった最初のファイルが提供されます(ブラウザの URL には元々リクエストされた URI が表示され続けます)。

次のコードは、デフォルトのファイル名を mydefault.html に変更する方法を示しています。

C#
public void Configure(IApplicationBuilder app)
{
    // Serve my app-specific default file, if present.
    DefaultFilesOptions options = new DefaultFilesOptions();
    options.DefaultFileNames.Clear();
    options.DefaultFileNames.Add("mydefault.html");
    app.UseDefaultFiles(options);
    app.UseStaticFiles();
}

UseFileServer

UseFileServer は、UseStaticFilesUseDefaultFilesUseDirectoryBrowser の機能を兼ね備えています。

次のコードは、静的ファイルとデフォルトファイルの提供を有効化しますが、ディレクトリ参照は許可しません:

C#
app.UseFileServer();

次のコードは、静的ファイル、デフォルトファイル、ディレクトリ参照を有効化します:

C#
app.UseFileServer(enableDirectoryBrowsing: true);

ディレクトリ参照を有効化した際のセキュリティリスクについては 検討事項 を参照してください。UseStaticFilesUseDefaultFiles、およびUseDirectoryBrowser と同様に、Web root の外部に存在するファイルを提供したい場合は、FileServerOptionsオブジェクトをインスタンス化して構成し、UseFileServer のパラメータとして渡してください。例えば、次のようなディレクトリ階層を持つ Web アプリケーションを考えてみてください:

  • wwwroot
    • css
    • images
    • ...
  • MyStaticFiles
    • test.png
    • default.html

上記のディレクトリ階層で、MyStaticFiles ディレクトリへの 静的ファイル、デフォルトファイル、ディレクトリ参照を有効にしたいとします。次のコードスニペットのように、FileServerOptions を設定するだけで実現できます。

C#
public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseFileServer(new FileServerOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"MyStaticFiles")),
        RequestPath = new PathString("/StaticFiles"),
        EnableDirectoryBrowsing = true
    });
}

もし EnableDirectoryBrowsingtrue にセットした場合、Startup.ConfigureServicesの中で AddDirectoryBrowser 拡張メソッドを実行する必要があります:

C#
public void ConfigureServices(IServiceCollection services)
{
    services.AddDirectoryBrowser();
}

上記のディレクトリ階層とコードを使用すると、以下のようになります:

URI Response
http://<app>/StaticFiles/test.png MyStaticFiles/test.png
http://<app>/StaticFiles MyStaticFiles/default.html

もし MyStaticFiles ディレクトリ内に デフォルトファイルがなければ、http://<app>/StaticFiles はクリック可能なディレクトリのリストを返します:

Static files list

[!注意]
UseDefaultFilesUseDirectoryBrowser は http://<app>/StaticFiles という URL を末尾のスラッシュなしで扱うので、http://<app>/StaticFiles/ (末尾にスラッシュ付き)へのクライアント側のリダイレクトに問題を引き起こします。末尾にスラッシュなしの相対 URL は不正となるでしょう。

FileExtensionContentTypeProvider

FileExtensionContentTypeProvider クラスは、ファイル拡張子と コンテンツの MIME タイプをマッピングするためのコレクションを持っています。次のサンプルでは、いくつかのファイル拡張子が既知の MIME タイプに登録されており、".rtf" は置き換えられ、".mp4" は削除されています。

C#
public void Configure(IApplicationBuilder app)
{
    // 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(Directory.GetCurrentDirectory(), @"wwwroot", "images")),
        RequestPath = new PathString("/MyImages"),
        ContentTypeProvider = provider
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot", "images")),
        RequestPath = new PathString("/MyImages")
    });
}

MIME コンテンツタイプ を参照してください。

非標準コンテンツタイプ

Static file middleware はおよそ 400 の既知のファイルコンテンツタイプを認識します。もしユーザーが不明なコンテンツタイプのファイルをリクエストした場合、Static file middleware は HTTP 404 (Not found) レスポンスを返します。もしディレクトリ参照が有効な場合、そのファイルへのリンクは表示されますが、そのリンクの URI へアクセスは HTTP 404 エラーを返します。

次のコードは、不明なコンテンツタイプの提供を有効にし、不明なファイルを画像として描画します。

C#
public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(new StaticFileOptions()
    {
        ServeUnknownFileTypes = true,
        DefaultContentType = "image/png"
    });
}

上記のコードで、不明なコンテンツタイプのファイルへのリクエストを画像として返すようになります。

[!警告]
ServeUnknownFileTypes の有効化はセキュリティリスクであり、使用することはお勧めしません。FileExtensionContentTypeProvider(後述)は、標準的でない拡張子をもつファイルを提供するためのより安全な代替手段を提供します。

検討事項

[!警告]
UseDirectoryBrowserUseStaticFiles は機密漏洩の可能性があります。本番環境ではディレクトリ参照を有効化しないことをお勧めします。UseStaticFilesUseDirectoryBrowser を使って有効化したディレクトリは、ディレクトリ全体とサブディレクトリ全てがアクセス可能になるので、注意してください。<content root>/wwwroot などの独自のディレクトリに公開コンテンツを保存し、アプリケーションビューや設定ファイルなどから分離しておくことをお勧めします。

  • UseDirectoryBrowser および UseStaticFiles で公開されるコンテンツの URL は、その基となるファイルシステムの大文字小文字の区別および文字制限に左右されます。例えば、Windows は大文字小文字を区別しませんが、Mac と Linux は区別します。

  • IIS でホストされる ASP.NET Core アプリケーションは、ASP.NET Core モジュールを使用して、静的ファイルへのリクエストを含むすべてのリクエストをアプリケーションに転送します。IIS 静的ファイルハンドラーは使用されることはありません。なぜなら、ASP.NET Core モジュールが先にリクエストを処理してしまうため、IIS 静的ファイルハンドラーがリクエストを処理するチャンスがないからです。

  • IIS 静的ファイルハンドラーを(サーバーや Web サイトレベルで)削除するには:

    • モジュール機能に移動し
    • リストの中から StaticFileModule を選択し
    • 操作サイドバー内の削除をタップします

[!警告]
もし IIS 静的ファイルハンドラーが有効で、かつ、ASP.NET Core モジュール (ANCM) が正しく構成されていない場合(例えば web.config がデプロイされていないなど)、静的ファイルが提供されてしまいます。

  • (C# と Razor を含む)コードファイルは、アプリケーションプロジェクトの Web root(デフォルトでは wwwroot)の外側に配置すべきです。 こうすることで、アプリケーションのクライアント側のコンテンツとサーバー側のソースコードが明確に分離され、サーバー側のコードの漏洩を防ぎます。

その他のリソース

3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1