博客
关于我
.NET Core开发实战(第24课:文件提供程序:让你可以将文件放在任何地方)--学习笔记
阅读量:416 次
发布时间:2019-03-06

本文共 3925 字,大约阅读时间需要 13 分钟。

24 | 文件提供程序:让你可以将文件放在任何地方

文件提供程序核心类型:

1、IFileProvider

2、IFileInfo

3、IDirectoryContents

IFileProvider 是访问各种各样文件提供程序的接口

通过这样子抽象的定义,让我们与具体的抽象文件的读取的代码进行了隔离

这样的好处是我们可以从不同的地方去读取文件,不仅仅是我们的物理文件,也可以是嵌入式文件,甚至可以说是云端上面的其他 API 提供的文件

内置的提供程序有三种:

(1)PhysicalFileProvider:物理文件的提供程序

(2)EmbeddedFileProvider:嵌入式的提供程序

(3)CompositeFileProvider:组合文件的提供程序

组合文件的提供程序是指当我们有多种文件数据来源的时候,可以将这些源合并为一个目录一样,让我们像在使用同一个目录一样使用我们的文件系统

首先我们可以看一下 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
, 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 来代替的),读取文件流

接下来通过代码看一下

首先添加 microsoft.extensions.fileproviders 相关 nuget 包引用

// 定义一个物理文件的提供程序,把我们当前应用程序的根目录映射出来IFileProvider provider1 = new PhysicalFileProvider(AppDomain.CurrentDomain.BaseDirectory);// 获取到这个目录下面的所有内容var contents = provider1.GetDirectoryContents("/");foreach (var item in contents){    // 打印文件名    Console.WriteLine(item.Name);}

启动程序可以看到控制台输出了编译目录下面的文件

FileProviderDemo.deps.jsonFileProviderDemo.dllFileProviderDemo.exeFileProviderDemo.pdbFileProviderDemo.runtimeconfig.dev.jsonFileProviderDemo.runtimeconfig.jsonMicrosoft.Extensions.FileProviders.Abstractions.dllMicrosoft.Extensions.FileProviders.Composite.dllMicrosoft.Extensions.FileProviders.Embedded.dllMicrosoft.Extensions.FileProviders.Physical.dllMicrosoft.Extensions.FileSystemGlobbing.dllMicrosoft.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

    

然后把它的属性设置为嵌入的资源,而不是内容

这样的设置的话,我们可以看一下对工程文件有什么影响

编辑项目可以看到我们把这个文件定义为嵌入式资源

再次读取这个文件

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.jsonFileProviderDemo.dllFileProviderDemo.exeFileProviderDemo.pdbFileProviderDemo.runtimeconfig.dev.jsonFileProviderDemo.runtimeconfig.jsonMicrosoft.Extensions.FileProviders.Abstractions.dllMicrosoft.Extensions.FileProviders.Composite.dllMicrosoft.Extensions.FileProviders.Embedded.dllMicrosoft.Extensions.FileProviders.Physical.dllMicrosoft.Extensions.FileSystemGlobbing.dllMicrosoft.Extensions.Primitives.dllemb.html

这就说明可以像在访问同一个目录一样,访问不同的文件提供程序目录,这就意味着实际上是可以通过实现简单的 IFileProvider 和 IFileInfo 就可以实现自己的文件提供程序

这些文件提供程序举一个场景比如说可以通过 OSS 的这种远程存储的方式将文件读取出来并且提供给应用程序,但是应用程序并不需要做特殊的配置,只需要把 OSS 提供的程序注入到系统里面,只需要按照 IFileProvider 提供的接口来读取文件,就可以做到像在读取本地文件一样,也就是说可以借助这套框架读取任意位置的文件

GitHub源码链接:

本作品采用进行许可。

欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

你可能感兴趣的文章
Mysql索引、命令重点介绍
查看>>
mysql索引、索引优化(这一篇包括所有)
查看>>
MySql索引为什么使用B+树
查看>>
WARNING!VisualDDK wizard was unable to find any DDK/WDK installed on your system.
查看>>
Mysql索引优化
查看>>
MySQl索引创建
查看>>
mysql索引创建及使用注意事项
查看>>
mysql索引创建和使用注意事项
查看>>
MySQL索引原理以及查询优化
查看>>
Mysql索引合并(index merge)导致的死锁问题
查看>>
mysql索引底层数据结构和算法
查看>>
Mysql索引底层结构的分析
查看>>
MySQL索引底层:B+树详解
查看>>
Mysql索引总结
查看>>
mysql索引最左匹配原则理解以及常见的sql使用的索引情况的实测
查看>>
Mysql索引类型
查看>>
MySQL索引背后的数据结构及算法原理
查看>>
mysql索引能重复吗_mysql “索引”能重复吗?“唯一索引”与“索引”区别是什么?...
查看>>
Mysql索引(2):索引结构
查看>>
Mysql索引(4):索引语法
查看>>