.NET Core开发实战(第24课:文件提供程序:让你可以将文件放在任何地方)--学习笔记
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<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 来代替的),读取文件流
接下来通过代码看一下
首先添加 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.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 提供的接口来读取文件,就可以做到像在读取本地文件一样,也就是说可以借助这套框架读取任意位置的文件
GitHub源码链接:
https://github.com/MingsonZheng/DotNetCoreDevelopmentActualCombat/tree/main/FileProviderDemo



本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。
.NET Core开发实战(第24课:文件提供程序:让你可以将文件放在任何地方)--学习笔记的更多相关文章
- .NET Core开发实战(第11课:文件配置提供程序)--学习笔记
11 | 文件配置提供程序:自由选择配置的格式 文件配置提供程序 Microsoft.Extensions.Configuration.Ini Microsoft.Extensions.Configu ...
- 2月送书福利:ASP.NET Core开发实战
大家都知道我有一个公众号“恰童鞋骚年”,在公众号2020年第一天发布的推文<2020年,请让我重新介绍我自己>中,我曾说到我会在2020年中每个月为所有关注“恰童鞋骚年”公众号的童鞋们送一 ...
- macOS使用ABP.vNext Core开发CMS系统(一) 让程序跑起来
macOS使用ABP.vNext Core开发CMS系统(一) 让程序跑起来--2020年10月5日 国庆假期,陪老婆的同时也不能忘记给自己充充电,这不想搞个CMS系统,考虑自己的时间并不多,所以想找 ...
- 2、SpringBoot接口Http协议开发实战8节课(1-6)
1.SpringBoot2.xHTTP请求配置讲解 简介:SpringBoot2.xHTTP请求注解讲解和简化注解配置技巧 1.@RestController and @RequestMapping是 ...
- [ASP.NET Core开发实战]开篇词
前言 本系列课程文章主要是学习官方文档,再输出自己学习心得,希望对你有所帮助. 课程大纲 本系列课程主要分为三个部分:基础篇.实战篇和部署篇. 希望通过本系列课程,能让大家初步掌握使用ASP.NET ...
- [ASP.NET Core开发实战]基础篇06 配置
配置,是应用程序很重要的组成部分,常常用于提供信息,像第三方应用登录钥匙.上传格式与大小限制等等. ASP.NET Core提供一系列配置提供程序读取配置文件或配置项信息. ASP.NET Core项 ...
- [ASP.NET Core开发实战]基础篇03 中间件
什么是中间件 中间件是一种装配到应用管道,以处理请求和响应的组件.每个中间件: 选择是否将请求传递到管道中的下一个中间件. 可在管道中的下一个中间件前后执行. ASP.NET Core请求管道包含一系 ...
- 2、SpringBoot接口Http协议开发实战8节课(7-8)
7.SpringBoot2.x文件上传实战 简介:讲解HTML页面文件上传和后端处理实战 1.讲解springboot文件上传 MultipartFile file,源自SpringMVC 1)静态页 ...
- [ASP.NET Core开发实战]基础篇04 主机
主机定义 主机是封闭应用资源的对象. 设置主机 主机通常由 Program 类中的代码配置.生成和运行. HTTP项目(ASP.NET Core项目)创建泛型主机: public class Prog ...
- [ASP.NET Core开发实战]基础篇02 依赖注入
ASP.NET Core的底层机制之一是依赖注入(DI)设计模式,因此要好好掌握依赖注入的用法. 什么是依赖注入 我们看一下下面的例子: public class MyDependency { pub ...
随机推荐
- 运行vue项目时报错“ValidationError: Progress Plugin Invalid Options”
https://blog.csdn.net/M_Nobody/article/details/123135041?spm=1001.2101.3001.6650.1&utm_medium=di ...
- SpringBoot 集成短信和邮件
准备工作 1.集成邮件 以QQ邮箱为例 在发送邮件之前,要开启POP3和SMTP协议,需要获得邮件服务器的授权码,获取授权码: 1.设置>账户 在账户的下面有一个开启SMTP协议的开关并进行密码 ...
- P1228-递归【黄】
这道大递归我一开始就找对了方向,不过了MLE,然后从网上搜索到了一个贼有用的概念--尾递归,即如果递归的下一句就是return且没有返回值或者返回值不含有递归函数则编译器会做优化,不会压入新的函数而是 ...
- 洛谷 P9683 A Certain Forbidden Index 题解
题目链接:\(\color{Purple}\texttt{P9683 A Certain Forbidden Index}\). 填坑.提供一个相对好写的做法. 考虑把一堆不交的区间绑在一起问(即先询 ...
- SV 字符串类型
概述 常见使用方式 string b; string b=""; // 拼接字符串 string a = {"hi",b}; // 将字符串a赋值给[15:0] ...
- 【C++】在搞touchgfx时遇见了一个初始化列表顺序与类中定义不一致的问题,error:when initialized here [-Werror=reorder]
在搞touchgfx时遇见了一个初始化列表顺序与类中定义不一致的问题,error:when initialized here [-Werror=reorder] 初始化列表顺序与类中定义顺序不一致错误 ...
- Mygin实现上下文
本篇是Mygin的第三篇 目的 将路由独立出来,方便后续扩展修改 上下文Context,对http.ResponseWriter和http.Request进行封装,实现对JSON.HTML等的支持 路 ...
- [转帖]高并发下nginx配置模板
user web; # One worker process per CPU core. worker_processes 8; # Also set # /etc/s ...
- [转帖]你应该知道的Shell 脚本的经典十三问
https://blog.csdn.net/wangzhicheng987/article/details/131031344 1. 为何叫做shell? 我们知道计算机的运作不能离开硬件,但使用者却 ...
- [转帖]PD 配置文件描述
https://docs.pingcap.com/zh/tidb/stable/pd-configuration-file PD 配置文件比命令行参数支持更多的选项.你可以在 conf/config. ...