.NET Core开发实战(第24课:文件提供程序:让你可以将文件放在任何地方)--学习笔记...
24 | 文件提供程序:讓你可以將文件放在任何地方
文件提供程序核心類型:
1、IFileProvider
2、IFileInfo
3、IDirectoryContents
IFileProvider 是訪問各種各樣文件提供程序的接口
通過這樣子抽象的定義,讓我們與具體的抽象文件的讀取的代碼進行了隔離
這樣的好處是我們可以從不同的地方去讀取文件,不僅僅是我們的物理文件,也可以是嵌入式文件,甚至可以說是云端上面的其他 API 提供的文件
內置的提供程序有三種:
(1)PhysicalFileProvider:物理文件的提供程序
(2)EmbeddedFileProvider:嵌入式的提供程序
(3)CompositeFileProvider:組合文件的提供程序
組合文件的提供程序是指當我們有多種文件數據來源的時候,可以將這些源合并為一個目錄一樣,讓我們像在使用同一個目錄一樣使用我們的文件系統
源碼鏈接:
https://github.com/witskeeper/geektime/tree/master/samples/FileProviderDemo
首先我們可以看一下 IFileProvider 的定義
namespace Microsoft.Extensions.FileProviders {public interface IFileProvider{// 輸入是一個相對的路徑IFileInfo GetFileInfo(string subpath);// 獲取指定目錄下的目錄信息IDirectoryContents GetDirectoryContents(string subpath);IChangeToken Watch(string filter);} }IDirectoryContents
namespace Microsoft.Extensions.FileProviders {public interface IDirectoryContents : IEnumerable<IFileInfo>, IEnumerable{bool Exists { get; }} }這個接口實際上就是 IFileInfo 的一個集合,還有一個屬性是否存在,表示當前目錄是否存在,如果存在的話,我們可以從它內部枚舉到我們的所有文件
IFileInfo
namespace Microsoft.Extensions.FileProviders {public interface IFileInfo{bool Exists { get; }long Length { get; }string PhysicalPath { get; }string Name { get; }DateTimeOffset LastModified { get; }bool IsDirectory { get; }Stream CreateReadStream();} }IFileInfo 有幾個屬性:是否存在,文件長度,物理地址,文件名,最后修改時間,是否是一個目錄(有可能獲取到的文件并不是一個真實的文件,它可能是一個目錄,那也就是用 IFileInfo 來代替的),讀取文件流
接下來通過代碼看一下
// 定義一個物理文件的提供程序,把我們當前應用程序的根目錄映射出來 IFileProvider provider1 = new PhysicalFileProvider(AppDomain.CurrentDomain.BaseDirectory);// 獲取到這個目錄下面的所有內容 var contents = provider1.GetDirectoryContents("/");foreach (var item in contents) {// 打印文件名Console.WriteLine(item.Name); }啟動程序可以看到控制臺輸出了編譯目錄下面的文件
FileProviderDemo.deps.json FileProviderDemo.dll FileProviderDemo.exe FileProviderDemo.pdb FileProviderDemo.runtimeconfig.dev.json FileProviderDemo.runtimeconfig.json Microsoft.Extensions.FileProviders.Abstractions.dll Microsoft.Extensions.FileProviders.Composite.dll Microsoft.Extensions.FileProviders.Embedded.dll Microsoft.Extensions.FileProviders.Physical.dll Microsoft.Extensions.FileSystemGlobbing.dll Microsoft.Extensions.Primitives.dll如果我們要讀文件流的話,可以通過 CreateReadStream
foreach (var item in contents) {// 讀取文件流var stream = item.CreateReadStream();// 打印文件名Console.WriteLine(item.Name); }接下來看一下嵌入式的提供程序,它是指編譯時把文件嵌入到程序集內部,就像源文件一樣,但是與通常的資源文件不同的是,我們可以像讀取目錄一樣讀取我們的文件
IFileProvider provider2 = new EmbeddedFileProvider(typeof(Program).Assembly);這里我們創建了一個 emb.html
<!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head><meta charset="utf-8" /><title></title> </head> <body></body> </html>然后把它的屬性設置為嵌入的資源,而不是內容
這樣的設置的話,我們可以看一下對工程文件有什么影響
編輯項目可以看到我們把這個文件定義為嵌入式資源
<ItemGroup><EmbeddedResource Include="emb.html" /></ItemGroup>再次讀取這個文件
IFileProvider provider2 = new EmbeddedFileProvider(typeof(Program).Assembly);var html = provider2.GetFileInfo("emb.html");斷點調試查看文件信息
可以看到 html 這個文件是否存在,是否目錄,最后修改時間,長度,名字,物理路徑
這就是可以通過嵌入式的文件提供程序來讀取編譯時構建到程序集里面的資源
最后一個就是組合文件提供程序,它的作用就是將各種提供程序組合成一個目錄,讓我們可以訪問它
// 傳入前面的兩種文件提供程序到組合提供程序里面,它可以傳入多個文件提供程序 IFileProvider provider = new CompositeFileProvider(provider1, provider2);var contents = provider.GetDirectoryContents("/");foreach (var item in contents) {Console.WriteLine(item.Name); }啟動程序可以看到,不僅輸出了程序集,編譯構建出來的文件,同時還輸出資源文件 emb.html
FileProviderDemo.deps.json FileProviderDemo.dll FileProviderDemo.exe FileProviderDemo.pdb FileProviderDemo.runtimeconfig.dev.json FileProviderDemo.runtimeconfig.json Microsoft.Extensions.FileProviders.Abstractions.dll Microsoft.Extensions.FileProviders.Composite.dll Microsoft.Extensions.FileProviders.Embedded.dll Microsoft.Extensions.FileProviders.Physical.dll Microsoft.Extensions.FileSystemGlobbing.dll Microsoft.Extensions.Primitives.dll emb.html這就說明可以像在訪問同一個目錄一樣,訪問不同的文件提供程序目錄,這就意味著實際上是可以通過實現簡單的 IFileProvider 和 IFileInfo 就可以實現自己的文件提供程序
這些文件提供程序舉一個場景比如說可以通過 OSS 的這種遠程存儲的方式將文件讀取出來并且提供給應用程序,但是應用程序并不需要做特殊的配置,只需要把 OSS 提供的程序注入到系統里面,只需要按照 IFileProvider 提供的接口來讀取文件,就可以做到像在讀取本地文件一樣,也就是說可以借助這套框架讀取任意位置的文件
總結
以上是生活随笔為你收集整理的.NET Core开发实战(第24课:文件提供程序:让你可以将文件放在任何地方)--学习笔记...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [头脑风暴] 解读Docker Brid
- 下一篇: 在Ocelot中使用自定义的中间件(二)