ASP.NET Core でのファイル プロバイダー

作成者: Steve Smith

ASP.NET Core は、ファイル プロバイダーを使用してファイル システムへのアクセスを抽象化します。 ファイル プロバイダーは、ASP.NET Core フレームワーク全体で使用されます。 次に例を示します。

  • IWebHostEnvironment では、アプリのコンテンツ ルートWeb ルートIFileProvider 型として公開されます。
  • 静的ファイル ミドルウェアでは、ファイル プロバイダーを使用して静的なファイルを見つけます。
  • Razor では、ファイル プロバイダーを使用してページとビューを見つけます。
  • .NET Core Tooling では、ファイル プロバイダーと glob パターンを使用して、公開するファイルを指定します。

サンプル コードを表示またはダウンロードします (ダウンロード方法)。

ファイル プロバイダーのインターフェイス

プライマリ インターフェイスは IFileProvider です。 IFileProvider では次のためのメソッドが公開されます。

IFileInfo ではファイルを操作するためのメソッドとプロパティが提供されます。

IFileInfo.CreateReadStream メソッドを使用して、ファイルから情報を読み取ることができます。

FileProviderSample サンプル アプリでは、依存関係の挿入を介してアプリ全体で使用するために、Startup.ConfigureServices でファイル プロバイダーを構成する方法が示されています。

ファイル プロバイダーの実装

次の表に、IFileProvider の実装の一覧を示します。

実装 説明
複合ファイル プロバイダー その他の 1 つまたは複数のプロバイダーからのファイルおよびディレクトリへのアクセスを結合するために使用します。
マニフェスト埋め込みファイル プロバイダー アセンブリに埋め込まれているファイルにアクセスする場合に使用します。
物理ファイル プロバイダー システムの物理ファイルにアクセスするために使用します。

物理ファイル プロバイダー

PhysicalFileProvider は、物理ファイル システムへのアクセス許可を提供します。 PhysicalFileProvider では、System.IO.File 型が使用され (物理プロバイダーの場合)、すべてのパスのスコープが 1 つのディレクトリとその子ディレクトリに設定されます。 このスコープ設定により、指定されたディレクトリとその子ディレクトリを除くファイル システムにアクセスできなくなります。 PhysicalFileProvider を作成して使用する最も一般的なシナリオは、依存関係の挿入を通してコンストラクターで IFileProvider を要求する場合です。

このプロバイダーを直接インスタンス化するときは、絶対ディレクトリ パスが要求され、そのプロバイダーを使用して行われるすべての要求のベース パスとして機能します。 glob パターンはディレクトリ パスではサポートされていません。

次のコードは、PhysicalFileProvider を使用してディレクトリの内容とファイルの情報を取得する方法を示しています。

var provider = new PhysicalFileProvider(applicationRoot);
var contents = provider.GetDirectoryContents(string.Empty);
var filePath = Path.Combine("wwwroot", "js", "site.js");
var fileInfo = provider.GetFileInfo(filePath);

前の例の型は次のとおりです。

  • providerIFileProvider です。
  • contentsIDirectoryContents です。
  • fileInfoIFileInfo です。

ファイル プロバイダーを使用して、applicationRoot で指定したディレクトリ全体を反復処理したり、GetFileInfo を呼び出してファイル情報を取得したりできます。 glob パターンを GetFileInfo メソッドに渡すことはできません。 ファイル プロバイダーは、applicationRoot ディレクトリの外部にはアクセスできません。

FileProviderSample サンプル アプリでは、IHostEnvironment.ContentRootFileProvider を使用して Startup.ConfigureServices メソッドにプロバイダーが作成されます。

var physicalProvider = _env.ContentRootFileProvider;

マニフェスト埋め込みファイル プロバイダー

ManifestEmbeddedFileProvider は、アセンブリに埋め込まれたファイルにアクセスするために使用されます。 ManifestEmbeddedFileProvider では、アセンブリにコンパイルされたマニフェストを使用して、埋め込まれたファイルの元のパスを再構築します。

埋め込みファイルのマニフェストを生成するには、次のようにします。

  1. Microsoft.Extensions.FileProviders.Embedded NuGet パッケージをプロジェクトに追加します。

  2. <GenerateEmbeddedFilesManifest> プロパティを true に設定します。 <EmbeddedResource> を使用して列挙するファイルを指定します:

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
      <PropertyGroup>
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.1.0" />
      </ItemGroup>
    
      <ItemGroup>
        <EmbeddedResource Include="Resource.txt" />
      </ItemGroup>
    
    </Project>
    

glob パターンを使用して、アセンブリに埋め込むファイルを 1 つまたは複数指定します。

FileProviderSample サンプル アプリでは、ManifestEmbeddedFileProvider が作成され、現在実行されているアセンブリがそのコンストラクターに渡されます。

Startup.cs:

var manifestEmbeddedProvider = 
    new ManifestEmbeddedFileProvider(typeof(Program).Assembly);

追加のオーバーロードを使用すると、次のことが可能になります。

  • 相対ファイル パスを指定します。
  • ファイルのスコープを最終変更日に設定します。
  • 埋め込みファイルのマニフェストを含む埋め込みリソースに名前を付けます。
オーバーロード 説明
ManifestEmbeddedFileProvider(Assembly, String) 必要に応じて相対パスのパラメーター root を指定できます。 root を指定して、GetDirectoryContents の呼び出しのスコープを指定したパス以下のリソースに設定します。
ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset) 必要に応じて、相対パス パラメーター root および日付パラメーター lastModified (DateTimeOffset) を指定できます。 lastModified の日付では、IFileProvider によって返される IFileInfo インスタンスの最終更新日のスコープを設定します。
ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset) 必要に応じて、相対パス root、日付 lastModifiedmanifestName パラメーターを指定できます。 manifestName は、マニフェストを含む埋め込みリソースの名前を表します。

複合ファイル プロバイダー

CompositeFileProvider は、IFileProvider インスタンスを結合し、複数のプロバイダーからのファイルを操作するための 1 つのインターフェイスを公開します。 CompositeFileProvider を作成する場合、1 つまたは複数の IFileProvider インスタンスをそのコンストラクターに渡します。

FileProviderSample サンプル アプリでは、PhysicalFileProviderManifestEmbeddedFileProvider により、アプリのサービス コンテナーに登録されている CompositeFileProvider にファイルが提供されます。 次のコードは、プロジェクトの Startup.ConfigureServices メソッドにあります。

var physicalProvider = _env.ContentRootFileProvider;
var manifestEmbeddedProvider = 
    new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
var compositeProvider = 
    new CompositeFileProvider(physicalProvider, manifestEmbeddedProvider);

services.AddSingleton<IFileProvider>(compositeProvider);

変更の監視

IFileProvider.Watch メソッドでは、変更がないかどうか 1 つ以上のファイルまたはディレクトリを監視するシナリオを提供します。 Watch メソッド:

  • ファイル パス文字列を指定できます。これにより、glob パターンを使用して複数のファイルを指定できます。
  • IChangeToken を返します。

生成される変更トークンでは次のものが公開されます。

  • HasChanged:このプロパティを調べることで、変更があったかどうかを判断できます。
  • RegisterChangeCallback:指定したパス文字列に対して変更が検出されたときに呼び出されます。 各変更トークンは、1 つの変更への応答として、関連付けられたコールバックを呼び出すのみです。 定数の監視を有効にするには、TaskCompletionSource<TResult> を使用するか (以下を参照)、変更への応答として IChangeToken インスタンスを再作成します。

WatchConsole サンプル アプリでは、TextFiles ディレクトリの .txt ファイルが変更されるたびに、メッセージが書き込まれます。

private static readonly string _fileFilter = Path.Combine("TextFiles", "*.txt");

public static void Main(string[] args)
{
    Console.WriteLine($"Monitoring for changes with filter '{_fileFilter}' (Ctrl + C to quit)...");

    while (true)
    {
        MainAsync().GetAwaiter().GetResult();
    }
}

private static async Task MainAsync()
{
    var fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
    IChangeToken token = fileProvider.Watch(_fileFilter);
    var tcs = new TaskCompletionSource<object>();

    token.RegisterChangeCallback(state =>
        ((TaskCompletionSource<object>)state).TrySetResult(null), tcs);

    await tcs.Task.ConfigureAwait(false);

    Console.WriteLine("file changed");
}

Docker コンテナーやネットワーク共有など、一部のファイル システムは、変更通知を確実に送信しない可能性があります。 DOTNET_USE_POLLING_FILE_WATCHER 環境変数を 1 または true に設定して、変更がないかどうか、4 秒ごとにファイル システムをポーリングして確認します (構成不可)。

glob パターン

ファイル システム パスは、"glob (または globbing) パターン" と呼ばれるワイルドカード パターンを使用します。 これらのパターンを使用して、ファイルのグループを指定します。 2 つのワイルドカード文字は、*** です。

*
現在のフォルダー レベルにある任意の要素、任意のファイル名、または任意のファイル拡張子を照合します。 照合はファイル パス内の / 文字および . 文字によって終了します。

**
複数のディレクトリ レベルにわたって任意の要素を照合します。 ディレクトリ階層内の多数のファイルを再帰的に照合する場合に使用できます。

次の表は、glob パターンの一般的な例を示しています。

パターン 説明
directory/file.txt 特定のディレクトリ内の特定のファイルを照合します。
directory/*.txt 特定のディレクトリ内の .txt 拡張子を持つすべてのファイルを照合します。
directory/*/appsettings.json directory フォルダーのちょうど 1 つ下のレベルにあるディレクトリ内のすべての appsettings.json ファイルを照合します。
directory/**/*.txt directory フォルダーの下の任意の場所にある、 .txt 拡張子を持つすべてのファイルを照合します。

ASP.NET Core は、ファイル プロバイダーを使用してファイル システムへのアクセスを抽象化します。 ファイル プロバイダーは、ASP.NET Core フレームワークの全体で使用されます。

  • IHostingEnvironment では、アプリのコンテンツ ルートWeb ルートIFileProvider 型として公開されます。
  • 静的ファイル ミドルウェアでは、ファイル プロバイダーを使用して静的なファイルを見つけます。
  • Razor では、ファイル プロバイダーを使用してページとビューを見つけます。
  • .NET Core Tooling では、ファイル プロバイダーと glob パターンを使用して、公開するファイルを指定します。

サンプル コードを表示またはダウンロードします (ダウンロード方法)。

ファイル プロバイダーのインターフェイス

プライマリ インターフェイスは IFileProvider です。 IFileProvider では次のためのメソッドが公開されます。

IFileInfo ではファイルを操作するためのメソッドとプロパティが提供されます。

IFileInfo.CreateReadStream メソッドを使用してファイルから読み取ることができます。

サンプル アプリでは、依存関係の挿入を介してアプリ全体で使用するために、Startup.ConfigureServices でファイル プロバイダーを構成する方法を示します。

ファイル プロバイダーの実装

利用できる IFileProvider の実装は 3 つあります。

実装 説明
PhysicalFileProvider システムの物理ファイルにアクセスするために、物理プロバイダーが使用されます。
ManifestEmbeddedFileProvider アセンブリに埋め込まれているファイルにアクセスするために、マニフェストが埋め込まれたプロバイダーが使用されます。
CompositeFileProvider コンポジット プロパイダーは、その他の 1 つまたは複数のプロバイダーからのファイルおよびディレクトリに対するアクセスを結合する場合に使用されます。

PhysicalFileProvider

PhysicalFileProvider は、物理ファイル システムへのアクセス許可を提供します。 PhysicalFileProvider では、System.IO.File 型が使用され (物理プロバイダーの場合)、すべてのパスのスコープが 1 つのディレクトリとその子ディレクトリに設定されます。 このスコープ設定により、指定されたディレクトリとその子ディレクトリを除くファイル システムにアクセスできなくなります。 PhysicalFileProvider を作成して使用する最も一般的なシナリオは、依存関係の挿入を通してコンストラクターで IFileProvider を要求する場合です。

このプロバイダーを直接インスタンス化するときは、ディレクトリ パスが要求され、そのプロバイダーを使用して行われるすべての要求のベース パスとして機能します。

次のコードでは、PhysicalFileProvider の作成方法と、これを使ってディレクトリのコンテンツとファイル情報を取得する方法が示されます。

var provider = new PhysicalFileProvider(applicationRoot);
var contents = provider.GetDirectoryContents(string.Empty);
var fileInfo = provider.GetFileInfo("wwwroot/js/site.js");

前の例の型は次のとおりです。

  • providerIFileProvider です。
  • contentsIDirectoryContents です。
  • fileInfoIFileInfo です。

ファイル プロバイダーを使用して、applicationRoot で指定したディレクトリ全体を反復処理したり、GetFileInfo を呼び出してファイル情報を取得したりできます。 ファイル プロバイダーは、applicationRoot ディレクトリの外部にはアクセスできません。

サンプル アプリの Startup.ConfigureServices クラスでは、IHostingEnvironment.ContentRootFileProvider を使用してプロバイダーを作成しています。

var physicalProvider = _env.ContentRootFileProvider;

ManifestEmbeddedFileProvider

ManifestEmbeddedFileProvider は、アセンブリに埋め込まれたファイルにアクセスするために使用されます。 ManifestEmbeddedFileProvider では、アセンブリにコンパイルされたマニフェストを使用して、埋め込まれたファイルの元のパスを再構築します。

埋め込みファイルのマニフェストを生成するには、<GenerateEmbeddedFilesManifest> プロパティを true に設定します。 <EmbeddedResource> を使用して埋め込むファイルを指定します。

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
    <GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

  <ItemGroup>
    <EmbeddedResource Include="Resource.txt" />
  </ItemGroup>

</Project>

glob パターンを使用して、アセンブリに埋め込むファイルを 1 つまたは複数指定します。

サンプル アプリでは ManifestEmbeddedFileProvider を作成して、現在実行しているアセンブリをそのコンストラクターに渡します。

Startup.cs:

var manifestEmbeddedProvider = 
    new ManifestEmbeddedFileProvider(typeof(Program).Assembly);

追加のオーバーロードを使用すると、次のことが可能になります。

  • 相対ファイル パスを指定します。
  • ファイルのスコープを最終変更日に設定します。
  • 埋め込みファイルのマニフェストを含む埋め込みリソースに名前を付けます。
オーバーロード 説明
ManifestEmbeddedFileProvider(Assembly, String) 必要に応じて相対パスのパラメーター root を指定できます。 root を指定して、GetDirectoryContents の呼び出しのスコープを指定したパス以下のリソースに設定します。
ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset) 必要に応じて、相対パス パラメーター root および日付パラメーター lastModified (DateTimeOffset) を指定できます。 lastModified の日付では、IFileProvider によって返される IFileInfo インスタンスの最終更新日のスコープを設定します。
ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset) 必要に応じて、相対パス root、日付 lastModifiedmanifestName パラメーターを指定できます。 manifestName は、マニフェストを含む埋め込みリソースの名前を表します。

CompositeFileProvider

CompositeFileProvider は、IFileProvider インスタンスを結合し、複数のプロバイダーからのファイルを操作するための 1 つのインターフェイスを公開します。 CompositeFileProvider を作成する場合、1 つまたは複数の IFileProvider インスタンスをそのコンストラクターに渡します。

サンプル アプリでは、PhysicalFileProviderManifestEmbeddedFileProvider が、アプリのサービス コンテナーに登録されている CompositeFileProvider にファイルを提供します。

var physicalProvider = _env.ContentRootFileProvider;
var manifestEmbeddedProvider = 
    new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
var compositeProvider = 
    new CompositeFileProvider(physicalProvider, manifestEmbeddedProvider);

services.AddSingleton<IFileProvider>(compositeProvider);

変更の監視

IFileProvider.Watch メソッドによって、1 つまたは複数のファイルやディレクトリに変更がないかどうか監視するシナリオが提供されます。 Watch にはパス文字列を指定できます。ここでは、glob パターンを使用して複数のファイルを指定できます。 Watch では IChangeToken が返されます。 変更トークンでは次のものが公開されます。

  • HasChanged:このプロパティを調べることで、変更があったかどうかを判断できます。
  • RegisterChangeCallback:指定したパス文字列に対して変更が検出されたときに呼び出されます。 各変更トークンは、1 つの変更への応答として、関連付けられたコールバックを呼び出すのみです。 定数の監視を有効にするには、TaskCompletionSource<TResult> を使用するか (以下を参照)、変更への応答として IChangeToken インスタンスを再作成します。

サンプル アプリでは、WatchConsole コンソール アプリは、テキスト ファイルが変更されるたびにメッセージを表示するように構成されています。

private static PhysicalFileProvider _fileProvider = 
    new PhysicalFileProvider(Directory.GetCurrentDirectory());

public static void Main(string[] args)
{
    Console.WriteLine("Monitoring quotes.txt for changes (Ctrl-c to quit)...");

    while (true)
    {
        MainAsync().GetAwaiter().GetResult();
    }
}

private static async Task MainAsync()
{
    IChangeToken token = _fileProvider.Watch("quotes.txt");
    var tcs = new TaskCompletionSource<object>();

    token.RegisterChangeCallback(state => 
        ((TaskCompletionSource<object>)state).TrySetResult(null), tcs);

    await tcs.Task.ConfigureAwait(false);

    Console.WriteLine("quotes.txt changed");
}

Docker コンテナーやネットワーク共有など、一部のファイル システムは、変更通知を確実に送信しない可能性があります。 DOTNET_USE_POLLING_FILE_WATCHER 環境変数を 1 または true に設定して、変更がないかどうか、4 秒ごとにファイル システムをポーリングして確認します (構成不可)。

glob パターン

ファイル システム パスは、"glob (または globbing) パターン" と呼ばれるワイルドカード パターンを使用します。 これらのパターンを使用して、ファイルのグループを指定します。 2 つのワイルドカード文字は、*** です。

*
現在のフォルダー レベルにある任意の要素、任意のファイル名、または任意のファイル拡張子を照合します。 照合はファイル パス内の / 文字および . 文字によって終了します。

**
複数のディレクトリ レベルにわたって任意の要素を照合します。 ディレクトリ階層内の多数のファイルを再帰的に照合する場合に使用できます。

glob パターンの例

directory/file.txt
特定のディレクトリ内の特定のファイルを照合します。

directory/*.txt
特定のディレクトリ内の .txt 拡張子を持つすべてのファイルを照合します。

directory/*/appsettings.json
directory フォルダーのちょうど 1 つ下のレベルにあるディレクトリ内のすべての appsettings.json ファイルを照合します。

directory/**/*.txt
directory フォルダーの下の任意の場所にある、 .txt 拡張子を持つすべてのファイルを照合します。