Asp.Net Core 中的“虚拟目录”
原文链接:https://blog.csdn.net/sD7O95O/article/details/107587430
现在部署Asp.Net Core应用已经不再限制于Windows的IIS上,更多的是Docker容器、各种反向代理来部署。也有少部分用IIS部署的,IIS部署确实是又快又简单,图形化操作三下五除二就可以发布好一个系统了。在过去Asp.Net MVC 项目部署的时候,还常常使用IIS一个功能——虚拟目录。
虚拟目录可以直接定位到非项目的其他路径,将路径作为网站的一部分,可实现上传文件保存到其他盘符或间接的使用项目以外的静态文件。在Asp.Net MVC中从虚拟路径中存取文件也很简单,如:
1 | Server.MapPath( "~/Upload/liohuang.jpg" ); |
但在Asp.Net Core上不同,它被抽象出一个“文件系统”,也就是FileProvider。FileProvider是对所有实现了IFileProvider接口的所有类型以及对应对象的统称,文件系统在Artech蒋老师的《.NET Core的文件系统[2]:FileProvider是个什么东西?》文章中已经透析了,这里不在罗里吧嗦了。
这篇文章要解决的内容是:Asp.Net Core应用中,如何优雅的使用“虚拟目录”。
实操
首先,新建一个.Net Core WebApi空项目部署在D盘,“虚拟目录”假设物理路径在F盘,分别创建三个测试目录 F:/test1 、 F:/test2 和 F:/test3 ,目录里分别存放对应的文件1/2/3.jpg 和 mybook.txt 。
读取虚拟目录文件
在 Startup.ConfigureServices 注入 IFileProvider :
1 | services.AddSingleton<IFileProvider>( new PhysicalFileProvider( "F:\\test1" )); |
新建一个控制器,读取 mybook.txt 中的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | [ApiController] [Route( "[controller]/[action]" )] public class LioHuangController : ControllerBase { [HttpGet] public object GetFiles([FromServices]IFileProvider fileProvider) { var file = fileProvider.GetFileInfo( "mybook.txt" ); if (file.Exists) { return ReadTxtContent(file.PhysicalPath); } return 0; } /// <summary> /// 读取文本 /// </summary> private string ReadTxtContent( string Path) { if (!System.IO.File.Exists(Path)) { return "Not found!" ; } using (StreamReader sr = new StreamReader(Path, Encoding.UTF8)) { StringBuilder sb = new StringBuilder(); string content; while ((content = sr.ReadLine()) != null ) { sb.Append(content); } return sb.ToString(); } } } |
访问接口,接口读取文件之后,返回内容:
IFileProvider 接口采用目录来组织文件,并统一使用 IFileInfo 接口来表示, PhysicalPath 表示文件的物理路径。
1 2 3 4 5 6 7 8 9 | public interface IFileInfo { bool Exists { get ; } bool IsDirectory { get ; } DateTimeOffset LastModified { get ; } string Name { get ; } string PhysicalPath { get ; } Stream CreateReadStream(); } |
如多个虚拟目录,怎么处理?简单,注入多个 IFileProvider 即可:
1 2 3 | services.AddSingleton<IFileProvider>( new PhysicalFileProvider( "F:\\test1" )); services.AddSingleton<IFileProvider>( new PhysicalFileProvider( "F:\\test2" )); services.AddSingleton<IFileProvider>( new PhysicalFileProvider( "F:\\test3" )); |
代码修改为:
1 | public object GetFiles([FromServices] IEnumerable<IFileProvider> fileProviders) |
IEnumerable<IFileProvider> fileProviders 接口数组将会有三个,按注入的顺序对应不同的目录。当然,注入 IFileProvider 的时候,就可以封装一层了,下面再讲。
另外,有的说直接 ReadTxtContent("F:\test1\mybook.txt"); 不香吗?香,Asp.Net Core的访问权限要比Asp.Net MVC之前老版本项目要高许多,确实是可以直接读取项目以外的文件,但是并不适合直接去访问,除非说你只有一个地方使用到,那么就可以直接读取,但静态的文件的访问,就访问不到了,仅仅是后台读取而已。所以统一使用 IFileProvider 来约束,代码的可维护性要高许多。
静态文件访问
在Startup.Configure设置静态文件目录,即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | app.UseStaticFiles( new StaticFileOptions() { FileProvider = new PhysicalFileProvider( "F:\\test1" ), RequestPath = "/test" });; app.UseStaticFiles( new StaticFileOptions() { FileProvider = new PhysicalFileProvider( "F:\\test2" ), RequestPath = "/test" }); app.UseStaticFiles( new StaticFileOptions() { FileProvider = new PhysicalFileProvider( "F:\\test3" ), RequestPath = "/test" }); |
FileProvider 同上面所说的,设置好物理路径的根目录, RequestPath 则是访问路径的前缀,必须是斜杆 “/” 开头,访问地址前缀则为:
https://localhost:5001/test/
设置好之后,就可以访问项目以外的路径了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2022-06-21 Global.asax文件