- 2017/04/09(Sun) 時点の情報に基づいています
- 公式ドキュメント:Introduction to working with static files in ASP.NET Core
ASP.NET Core での 静的ファイルの扱い 概要
静的ファイルの提供
静的ファイルは通常 web root
(<content-root>/wwwroot)フォルダに配置されます。詳細については ASP.NET Core 入門 の「Content root と Web root」を参照してください。開発中は web root
が見つかるように、Content root をカレントディレクトリに指定するのが一般的です。
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 フォルダ配下に css、 images、 js といったフォルダが作成されます。images サブフォルダ内の画像にアクセスするための URI は以下のようになります:
http://<app>/images/<imageFileName>
http://localhost:9189/images/banner3.svg
静的ファイルを提供するためには、Middleware を構成して、静的ファイルをパイプラインに追加しなくてはなりません。Nuget で Microsoft.AspNetCore.StaticFiles パッケージの参照をプロジェクトに追加し、Startup.Configure
内で
UseStaticFiles
拡張メソッドを実行することで、Static file Middleware を構成することができます:
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");
}
});
}
静的ファイルの認可
Static file Middleware は認可のチェックを行いません。wwwroot 配下のファイルを含む、Static file Middleware によって提供されるファイルは全て公開されます。認可に基づいてファイルを提供するには:
-
wwwroot や Static file Middleware がアクセスできるディレクトリの外部にファイルを配置し、かつ
-
コントローラーアクションを通してファイルを提供するようにし、認可が適用される
FileResult
を返すようにします。
ディレクトリ参照を有効にする
ディレクトリ参照は、ユーザーに指定されたディレクトリ内のディレクトリとファイルのリストを参照可能にします。セキュリティの理由(検討事項を参照)からディレクトリ参照はデフォルトで無効にされています。ディレクトリ参照を有効にするには Startup.Configure
メソッド内で UseDirectoryBrowser
拡張メソッドを実行してください:
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 を追加してください:
public void ConfigureServices(IServiceCollection services)
{
services.AddDirectoryBrowser();
}
上記のコードは wwwroot/images フォルダへのディレクトリ参照を許可します。URL http://<app>/MyImages で参照でき、各ファイルやフォルダへのリンクは以下のとおりです:
ディレクトリ参照を有効にした際のセキュリティリスクについては 検討事項 を参照してください。
2つの app.UseStaticFiles
の呼び出しに注目してください。1つ目は wwwroot フォルダ内の CSS、images、JavaScript ファイルを提供し、2つ目は URL http://<app>/MyImages で wwwroot/images フォルダへのディレクトリ参照を許可します:
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
拡張メソッドを実行してください。
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 に変更する方法を示しています。
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
は、UseStaticFiles
、 UseDefaultFiles
、 UseDirectoryBrowser
の機能を兼ね備えています。
次のコードは、静的ファイルとデフォルトファイルの提供を有効化しますが、ディレクトリ参照は許可しません:
app.UseFileServer();
次のコードは、静的ファイル、デフォルトファイル、ディレクトリ参照を有効化します:
app.UseFileServer(enableDirectoryBrowsing: true);
ディレクトリ参照を有効化した際のセキュリティリスクについては 検討事項 を参照してください。UseStaticFiles
、UseDefaultFiles
、およびUseDirectoryBrowser
と同様に、Web root の外部に存在するファイルを提供したい場合は、FileServerOptionsオブジェクトをインスタンス化して構成し、UseFileServer のパラメータとして渡してください。例えば、次のようなディレクトリ階層を持つ Web アプリケーションを考えてみてください:
- wwwroot
- css
- images
- ...
- MyStaticFiles
- test.png
- default.html
上記のディレクトリ階層で、MyStaticFiles
ディレクトリへの 静的ファイル、デフォルトファイル、ディレクトリ参照を有効にしたいとします。次のコードスニペットのように、FileServerOptions
を設定するだけで実現できます。
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
});
}
もし EnableDirectoryBrowsing
を true
にセットした場合、Startup.ConfigureServices
の中で AddDirectoryBrowser
拡張メソッドを実行する必要があります:
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 はクリック可能なディレクトリのリストを返します:
[!注意]
UseDefaultFiles
とUseDirectoryBrowser
は http://<app>/StaticFiles という URL を末尾のスラッシュなしで扱うので、http://<app>/StaticFiles/ (末尾にスラッシュ付き)へのクライアント側のリダイレクトに問題を引き起こします。末尾にスラッシュなしの相対 URL は不正となるでしょう。
FileExtensionContentTypeProvider
FileExtensionContentTypeProvider
クラスは、ファイル拡張子と コンテンツの MIME タイプをマッピングするためのコレクションを持っています。次のサンプルでは、いくつかのファイル拡張子が既知の MIME タイプに登録されており、".rtf" は置き換えられ、".mp4" は削除されています。
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 エラーを返します。
次のコードは、不明なコンテンツタイプの提供を有効にし、不明なファイルを画像として描画します。
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles(new StaticFileOptions()
{
ServeUnknownFileTypes = true,
DefaultContentType = "image/png"
});
}
上記のコードで、不明なコンテンツタイプのファイルへのリクエストを画像として返すようになります。
[!警告]
ServeUnknownFileTypes
の有効化はセキュリティリスクであり、使用することはお勧めしません。FileExtensionContentTypeProvider
(後述)は、標準的でない拡張子をもつファイルを提供するためのより安全な代替手段を提供します。
検討事項
[!警告]
UseDirectoryBrowser
とUseStaticFiles
は機密漏洩の可能性があります。本番環境ではディレクトリ参照を有効化しないことをお勧めします。UseStaticFiles
やUseDirectoryBrowser
を使って有効化したディレクトリは、ディレクトリ全体とサブディレクトリ全てがアクセス可能になるので、注意してください。<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)の外側に配置すべきです。 こうすることで、アプリケーションのクライアント側のコンテンツとサーバー側のソースコードが明確に分離され、サーバー側のコードの漏洩を防ぎます。