静的ファイルを wwwroot 以外のフォルダに配置する

ページ作成日 :

環境

Visual Studio
  • Visual Studio 2019
ASP.NET Core
  • 3.1 (Razor ページ, MVC)

静的ファイルの既定の配置場所について

静的ファイル (.js や .css, .png など) は既定では wwwroot フォルダの下に置くことが決まっています。 これにより Web サイト利用者は HTML と一緒に .js ファイルや .css ファイルを直接参照することができ画面に反映させることができます。

この静的ファイルの既定配置フォルダが wwwroot になっているのは Startup.Configure メソッドに記述されている以下の app.UseStaticFiles メソッドを呼んでいるからです。

public class Startup
{
  // 省略

  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  {
    // 省略

    app.UseStaticFiles();

    // 省略
  }
}

物理フォルダ「wwwroot」のパスは、URL でいうと「https://<ホスト名>/」の箇所にあたり、 例として「wwwroot\image\sample.png」にあるファイルは URL では「https://<ホスト名>/image/sample.png」で参照できます。

wwwroot フォルダ以外に配置したファイルは基本的に Web 上で URL から参照することはできません。

wwwroot フォルダ以外に静的ファイルを配置する方法と URL での参照パスの変更

フォルダ構成

今回は wwwroot フォルダの機能は残しつつ、別フォルダに画像ファイルを配置し Web で参照できるようにしたいと思います。

プロジェクトのフォルダ構成は以下のようにし、Areas 内にある各サイトの Content フォルダ内にある画像ファイルを参照できるようにします。

この状態だと sample1.png にあるファイルを参照する URL は

  • https://<ホスト名>/areas/site1/content/image/sample1.png

  • https://<ホスト名>/site1/content/image/sample1.png

になるように思えるかもしれませんが、ここでは

  • https://<ホスト名>/site1/image/sample1.png

で参照できるようにします。

ちなみに wwwroot フォルダ以外に静的ファイルを配置した場合、ファイルのビルドアクションが なし になっている場合があります。 このままだと発行してもファイルが配置されませんので、必ず コンテンツ に設定しなおしてください。

プログラムの追加

wwwroot 以外のフォルダで静的ファイルを参照できるようにするには、以下のように Startup.Configure メソッド内で app.UseStaticFiles メソッドを追加で呼び出します。

// 追加
using Microsoft.Extensions.FileProviders;
using System.IO;

// 省略

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  // 省略

  // wwwroot フォルダで静的ファイル参照を有効にする
  app.UseStaticFiles();

  // Site1 用の物理コンテンツフォルダと参照 URL を紐づける
  app.UseStaticFiles(new StaticFileOptions()
  {
    FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Areas/Site1/Content")),
    RequestPath = "/Site1",
  });

  // Site2 用の物理コンテンツフォルダと参照 URL を紐づける
  app.UseStaticFiles(new StaticFileOptions()
  {
    FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Areas/Site2/Content")),
    RequestPath = "/Site2",
  });

  // 省略
}

app.UseStaticFiles メソッドを引数なしで呼び出すと wwwroot フォルダが有効になりますが、 第一引数に StaticFileOptions を渡すと追加設定が可能です。

StaticFileOptions.FileProvider プロパティには PhysicalFileProvider のインスタンスを渡しつつ、静的ファイルとして参照させたい物理フォルダを指定します。 ここで指定したパス配下のファイルが Web で参照できるファイルになります。 また、次の RequestPath プロパティの URL のルートにもなります。

env.ContentRootPath プロパティには Web プログラムのルートパス(物理パス)が含まれていますので、 これと対象フォルダへの相対パスを結合するとよいでしょう。

StaticFileOptions.RequestPath プロパティには静的ファイルを参照する URL のルートパスを記述します。 デフォルトの wwwroot では https://<ホスト名> が基準となっていますが、 上記コードのように RequestPath = "/Site1" と記述すると https://<ホスト名>/Site1 がルートとなります。 これにより Areas/Site1/Content/xxxx の物理パスと https://<ホスト名>/Site1/xxxx の URL が紐づきます。

sample1.png を例とすると Areas/Site1/Content/image/sample.png のファイルは https://<ホスト名>/Site1/image/sample.png のパスで参照できるというわけです。

動作確認

index.html に以下のように画像を参照できるように img タグを配置します。 パスは定義にそって site1 や site2 の画像も参照します。

<!-- 省略 -->

<div class="text-center">
	<h1 class="display-4">Welcome</h1>
	<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<!-- ここから追加 -->
<img src="~/image/sample.png" />
<img src="~/site1/image/sample1.png" />
<img src="~/site2/image/sample2.png" />
<!-- ここまで追加 -->

実行して画像が見えていれば成功です。