当前位置: 首页 > news >正文

《深入浅出.NET框架设计与实现》阅读笔记(四)

静态文件系统


通过ASP.NET Core 提供的静态文件模块和静态文件中间件,可以轻松的让应用程序拥有访问静态文件的功能,同时可以基于IFileProvider对象来自定义文件系统,如基于Redis做扩展文件系统

启动静态文件服务

Program.cs 类中,通过WebApplication的UseStaticFiles扩展方法启动。

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseStaticFiles();
app.Run();

默认存储目录(wwwroot)

默认情况下,静态文件存储在项目的wwwroot目录下。
在这里插入图片描述

  • 读取静态文件(以favicon.ico文件为例):https:// localhost:6379/favicon.ico
  • 读取静态文件(以README.md文件为例):https://localhost:6379/css/open-iconic/README.md

增加自定义静态目录文件

  • 调用UseStaticFiles方法时传递StaticFileOptions配置参数。
  • StaticFileOptionsFileProvider为指定的文件夹路径
  • StaticFileOptionsRequestPath为请求路径的前缀
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
//自定义静态文件目录
StaticFileOptions fileOpt = new()
{FileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),//指定文件夹目录RequestPath = "/StaticFiles"//自定义前缀
};
app.UseStaticFiles(fileOpt);
app.Run();
  • 指定了在项目文件目录下的MyStaticFiles文件夹
    在这里插入图片描述
  • 通过路径来获取想要的文件(以用户手册.pdf为例):https://localhost:6379/StaticFiles/用户手册.pdf
    在这里插入图片描述

自定义一个简单的文件系统

在ASP.NET Core中,允许开发人员自定义文件系统,可以利用IFileProvider接口来构建文件系统。

文件信息类(RedisFileInfo)

public class RedisFileInfo : IFileInfo
{/// <summary>/// 判断目录或文件是否真的存在/// </summary>public bool Exists { get; set; } = true;/// <summary>/// 表示是目录还是文件/// </summary>public bool IsDirectory { get; set; }/// <summary>/// 文件或目录最后一次修改的时间/// </summary>public DateTimeOffset LastModified { get; set; }/// <summary>/// 表示文件内容的字节长度/// </summary>public long Length => _fileContent.Length;/// <summary>/// 表示文件或目录的名字/// </summary>public string Name { get; set; }/// <summary>/// 表示文件或目录的物理路径/// </summary>public string PhysicalPath { get; set; }private readonly byte[] _fileContent;public Stream CreateReadStream(){var stream = new MemoryStream(_fileContent);stream.Position = 0;return stream;}public RedisFileInfo() { }public RedisFileInfo(string name, string content){Name = name;LastModified = DateTimeOffset.Now;_fileContent = Convert.FromBase64String(content);}public RedisFileInfo(string name,bool isDirectory){Name = name;LastModified = DateTimeOffset.Now; IsDirectory = isDirectory;}}

文件目录类(EnumerableDirectoryContents)

public class EnumerableDirectoryContents : IDirectoryContents
{private readonly IEnumerable<IFileInfo> _entries;public bool Exists => true;public EnumerableDirectoryContents(IEnumerable<IFileInfo> entries){_entries = entries;}public IEnumerator<IFileInfo> GetEnumerator(){return _entries.GetEnumerator();}IEnumerator IEnumerable.GetEnumerator(){return GetEnumerator();}
}

Redis配置文件(RedisFileOptions)

public class RedisFileOptions
{/// <summary>/// 配置Redius连接信息/// </summary>public string HostAndPort { get; set; }
}

文件系统逻辑处理类(RedisFileProvider)

    /// <summary>/// Redis文件解析器,只要用于通过指定的名称从Redis中读取存储的图片内容/// </summary>
public class RedisFileProvider : IFileProvider
{private readonly RedisFileOptions _options;private readonly ConnectionMultiplexer _redis;private static string NormalizePath(string path) => path.TrimStart('/').Replace('/', ':');/// <summary>/// 参数为Ioptions的好处是可以使用Options.Create()方法来直接生成/// </summary>/// <param name="options"></param>public RedisFileProvider(IOptions<RedisFileOptions> options){_options = options.Value;_redis = ConnectionMultiplexer.Connect(new ConfigurationOptions{EndPoints = { _options.HostAndPort }});}/// <summary>/// 获得指定的目录/// /// 通过/// </summary>/// <param name="subpath"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public IDirectoryContents GetDirectoryContents(string subpath){var db = _redis.GetDatabase();var server = _redis.GetServer(_options.HostAndPort);var list = new List<IFileInfo>();subpath = NormalizePath(subpath);foreach (var key in server.Keys(0, $"{subpath}*")){var k = "";if (subpath != "") k = key.ToString().Replace(subpath, "").Split(":")[0];else k = key.ToString().Split(":")[0];if (list.Find(f => f.Name == k) == null){//判断是否存在.if (k.IndexOf('.', StringComparison.OrdinalIgnoreCase) >= 0){list.Add(new RedisFileInfo(k, db.StringGet(k)));}else{list.Add(new RedisFileInfo(k, true));}}}if (list.Count == 0){return NotFoundDirectoryContents.Singleton;}return new EnumerableDirectoryContents(list);}/// <summary>/// 得到指定目录或文件的IFileInfo对象/// 通过subpath参数值再Redis客户端读取文件信息。/// </summary>/// <param name="subpath"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public IFileInfo GetFileInfo(string subpath){subpath = NormalizePath(subpath);var db = _redis.GetDatabase();var redisValue = db.StringGet(subpath);return !redisValue.HasValue ? new NotFoundFileInfo(subpath) : new RedisFileInfo(subpath, redisValue.ToString());}public IChangeToken Watch(string filter){throw new NotImplementedException();}
}

注入服务

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
//使用自定义文件系统
StaticFileOptions fileOpt = new()
{FileProvider = new RedisFileProvider(Options.Create(new RedisFileOptions{HostAndPort = "localhost:6379",}))
};
app.UseStaticFiles(fileOpt);

相关文章:

  • SOLIDWORKS Flow Simulation阀门内流体仿真
  • 基于乌鸦算法优化概率神经网络PNN的分类预测 - 附代码
  • 软件测试不是所有人都适合的
  • 腾讯云标准型SA4服务器AMD处理器性能测评
  • vue中实现图片懒加载的几种方法
  • 扭矩传感器信号模拟地、数据地与电源地
  • Docker 中的端口
  • 批量重命名软件推荐 A Better Finder Rename 12最新 for mac
  • Mysql开启binlog 和 打开gtid_mode
  • 【蓝桥杯软件赛 零基础备赛20周】第3周——填空题
  • 异步方法、async/await逃离回调地狱(Callback Hell)
  • 四川芸鹰蓬飞商务信息咨询有限公司是可靠的选择
  • 头哥实践平台之MapReduce基础实战
  • ARM64 linux并发与同步之经典自旋锁
  • 老师的保命大法
  • ----------
  • #Java异常处理
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • canvas 五子棋游戏
  • ES6--对象的扩展
  • Java 最常见的 200+ 面试题:面试必备
  • Spring Boot MyBatis配置多种数据库
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 记录一下第一次使用npm
  • 前端技术周刊 2019-02-11 Serverless
  • 前端自动化解决方案
  • 嵌入式文件系统
  • 巧用 TypeScript (一)
  • 通过git安装npm私有模块
  • 我看到的前端
  • 携程小程序初体验
  • No resource identifier found for attribute,RxJava之zip操作符
  • 1.Ext JS 建立web开发工程
  • ​Spring Boot 分片上传文件
  • #include
  • $ git push -u origin master 推送到远程库出错
  • (13):Silverlight 2 数据与通信之WebRequest
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (状压dp)uva 10817 Headmaster's Headache
  • .NET 5种线程安全集合
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .NET Framework 4.6.2改进了WPF和安全性
  • .NET 中让 Task 支持带超时的异步等待
  • .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)...