ASP.NET Core 中的檔案提供程式 遍歷資料夾讀取檔案資訊

菜鳥飛不動-公眾號 讀書ReadBook發表於2019-03-07

ASP.NET Core 通過檔案提供程式來抽象化檔案系統訪問。 在 ASP.NET Core 框架中使用檔案提供程式:

  • IHostingEnvironment 將應用的內容根和 Web 根作為 IFileProvider 型別公開。
  • 靜態檔案中介軟體使用檔案提供程式來查詢靜態檔案。
  • Razor 使用檔案提供程式來查詢頁面和檢視。
  • .NET Core 工具使用檔案提供程式和 glob 模式來指定應該釋出哪些檔案。

檢視或下載示例程式碼如何下載

檔案提供程式介面

主介面為 IFileProviderIFileProvider 公開方法以實現以下目的:

IFileInfo 提供用於處理檔案的方法和屬性:

可以使用 IFileInfo.CreateReadStream 方法從檔案讀取內容。

示例應用演示瞭如何在 Startup.ConfigureServices 中配置檔案提供程式,以便通過依賴關係注入在應用中使用。

檔案提供程式實現

IFileProvider 有三種實現。

實現描述
PhysicalFileProvider物理提供程式用於訪問系統的物理檔案。
ManifestEmbeddedFileProvider清單嵌入式提供程式用於訪問程式集中嵌入的檔案。
CompositeFileProvider複合式提供程式提供對一個或多個其他提供程式中的檔案和目錄的合併訪問。

PhysicalFileProvider

PhysicalFileProvider 提供對物理檔案系統的訪問。 PhysicalFileProvider 使用(物理提供程式的)System.IO.File 型別並將所有路徑範圍限制到目錄及其子目錄。 此範圍界定可防止訪問指定目錄和子目錄之外的檔案系統。 例項化此提供程式時,必須提供目錄路徑並將其作為使用提供程式發出的所有請求的基路徑。 可以直接例項化 PhysicalFileProvider 提供程式,也可以通過依賴關係注入請求建構函式中的 IFileProvider

靜態型別

下面的程式碼演示如何建立 PhysicalFileProvider 並用它來獲取目錄內容和檔案資訊:

C#複製

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 目錄外部的任何內容。

示例應用使用 IHostingEnvironment.ContentRootFileProvider 在應用的 Startup.ConfigureServices 類中建立提供程式:

C#複製

var physicalProvider = _env.ContentRootFileProvider;

使用依賴關係注入獲取檔案提供程式型別

將提供程式注入任何類建構函式,並將其分配給本地欄位。 在整個類的方法中使用該欄位來訪問檔案。

在示例應用中,IndexModel 類接收 IFileProvider 例項,獲取應用的基路徑的目錄內容。

Pages/Index.cshtml.cs:

C#複製

public class IndexModel : PageModel
{
    private readonly IFileProvider _fileProvider;

    public IndexModel(IFileProvider fileProvider)
    {
        _fileProvider = fileProvider;
    }

    public IDirectoryContents DirectoryContents { get; private set; }

    public void OnGet()
    {
        DirectoryContents = _fileProvider.GetDirectoryContents(string.Empty);
    }
}

在頁中迴圈訪問 IDirectoryContents

Pages/Index.cshtml:

CSHTML複製

<ul>
    @foreach (var item in Model.DirectoryContents)
    {
        if (item.IsDirectory)
        {
            <li><strong>@item.Name</strong></li>
        }
        else
        {
            <li>@item.Name - @item.Length bytes</li>
        }
    }
</ul>

ManifestEmbeddedFileProvider

ManifestEmbeddedFileProvider 用於訪問程式集內嵌入的檔案。 ManifestEmbeddedFileProvider 使用編譯到程式集中的某個清單來重建嵌入的檔案的原始路徑。

備註

ASP.NET Core 2.1 或更高版本中提供了 ManifestEmbeddedFileProvider。 若要訪問在 ASP.NET Core 2.0 或更早版本 的程式集中嵌入的檔案,請參閱本主題的 ASP.NET Core 1.x 版本

若要生成嵌入的檔案清單,請將 <GenerateEmbeddedFilesManifest> 屬性設定為 true。 指定要使用 嵌入的檔案:

C#複製

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

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
  </PropertyGroup>

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

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

</Project>

使用 glob 模式指定要嵌入到程式集中的一個或多個檔案。

示例應用建立 ManifestEmbeddedFileProvider 並將當前正在執行的程式集傳遞給其建構函式。

Startup.cs

C#複製

var manifestEmbeddedProvider = 
    new ManifestEmbeddedFileProvider(Assembly.GetEntryAssembly());

其他過載使你能夠:

  • 指定相對檔案路徑。
  • 將檔案範圍限制到上次修改日期。
  • 為包含嵌入檔案清單的嵌入資源命名。
過載描述
ManifestEmbeddedFileProvider(Assembly, String)接受一個可選的 root 相對路徑引數。 指定 root 將對 GetDirectoryContents 的呼叫範圍限制為提供的路徑下的那些資源。
ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset)接受一個可選的 root 相對路徑引數和一個 lastModified 日期 (DateTimeOffset) 引數。 lastModified 日期限制 IFileProvider 返回的 IFileInfo 例項的上次修改日期範圍。
ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset)接受一個可選的 root 相對路徑、lastModified 日期和 manifestName 引數。 manifestName 表示包含清單的嵌入資源的名稱。

CompositeFileProvider

CompositeFileProvider 結合了 IFileProvider 例項,以便公開一個介面來處理來自多個提供程式的檔案。 建立 CompositeFileProvider 時,將一個或多個 IFileProvider 例項傳遞給其建構函式。

在示例應用中,PhysicalFileProviderManifestEmbeddedFileProvider 向在應用的服務容器中註冊的 CompositeFileProvider 提供檔案:

C#複製

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

services.AddSingleton<IFileProvider>(compositeProvider);

監視更改

IFileProvider.Watch 方法提供了一個方案來監視一個或多個檔案或目錄是否發生更改。 Watch 接受路徑字串,它可以使用 glob 模式指定多個檔案。 Watch 返回 IChangeToken。 更改令牌會公開以下內容:

  • HasChanged:可檢查此屬性以確定是否已發生更改。
  • RegisterChangeCallback:檢測到指定的路徑字串發生更改時呼叫此屬性。 每個更改令牌僅呼叫其關聯的回撥來響應單個更改。 若要啟用持續監視,請使用 TaskCompletionSource(如下所示)或重新建立 IChangeToken 例項以響應更改。

在示例應用中,WatchConsole 控制檯應用配置為每次修改了文字檔案時顯示一條訊息:

C#複製

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 環境變數設定為 1true 以每隔四秒輪詢一次檔案系統,確認是否發生更改(不可配置)。

glob 模式

檔案系統路徑使用名為 glob(或通配)模式的萬用字元模式。 使用這些模式指定檔案的組。 兩個萬用字元分別是 ***


匹配當前資料夾級別的任何內容、任何檔名或任何副檔名。 匹配由檔案路徑中的 /. 字元終止。

**
匹配多個目錄級別的任何內容。 可用於以遞迴方式匹配目錄層次結構中的許多檔案。

glob 模式示例

directory/file.txt
匹配特定目錄中的特定檔案。

directory/*.txt
匹配特定目錄中帶 .txt 副檔名的所有檔案。

directory/*/appsettings.json
匹配正好位於“目錄”資料夾中下一級目錄中的所有 appsettings.json 檔案。

directory/*/*.txt*
匹配在“目錄”資料夾下任何位置找到的帶 .txt 副檔名的所有檔案。

相關文章