博客
关于我
.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中interactive_timeout和wait_timeout的区别
查看>>
mysql中int、bigint、smallint 和 tinyint的区别、char和varchar的区别详细介绍
查看>>
mysql中json_extract的使用方法
查看>>
mysql中json_extract的使用方法
查看>>
mysql中kill掉所有锁表的进程
查看>>
mysql中like % %模糊查询
查看>>
MySql中mvcc学习记录
查看>>
mysql中null和空字符串的区别与问题!
查看>>
MySQL中ON DUPLICATE KEY UPDATE的介绍与使用、批量更新、存在即更新不存在则插入
查看>>
MYSQL中TINYINT的取值范围
查看>>
MySQL中UPDATE语句的神奇技巧,让你操作数据库如虎添翼!
查看>>
Mysql中varchar类型数字排序不对踩坑记录
查看>>
MySQL中一条SQL语句到底是如何执行的呢?
查看>>
MySQL中你必须知道的10件事,1.5万字!
查看>>
MySQL中使用IN()查询到底走不走索引?
查看>>
Mysql中使用存储过程插入decimal和时间数据递增的模拟数据
查看>>
MySql中关于geometry类型的数据_空的时候如何插入处理_需用null_空字符串插入会报错_Cannot get geometry object from dat---MySql工作笔记003
查看>>
mysql中出现Incorrect DECIMAL value: '0' for column '' at row -1错误解决方案
查看>>
mysql中出现Unit mysql.service could not be found 的解决方法
查看>>
mysql中出现update-alternatives: 错误: 候选项路径 /etc/mysql/mysql.cnf 不存在 dpkg: 处理软件包 mysql-server-8.0的解决方法(全)
查看>>