Asp.Net Core 中的“虚拟目录”
写在前面
现在部署Asp.Net Core应用已经不再限制于Windows的IIS上,更多的是Docker容器、各种反向代理来部署。也有少部分用IIS部署的,IIS部署确实是又快又简单,图形化操作三下五除二就可以发布好一个系统了。在过去Asp.Net MVC 项目部署的时候,还常常使用IIS一个功能——虚拟目录。
虚拟目录可以直接定位到非项目的其他路径,将路径作为网站的一部分,可实现上传文件保存到其他盘符或间接的使用项目以外的静态文件。在Asp.Net MVC中从虚拟路径中存取文件也很简单,如
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 :
services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\\test1"));
新建一个控制器,读取 mybook.txt 中的内容:
[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 表示文件的物理路径。
public interface IFileInfo
{bool Exists { get; }bool IsDirectory { get; }DateTimeOffset LastModified { get; }string Name { get; }string PhysicalPath { get; }Stream CreateReadStream();
}
如多个虚拟目录,怎么处理?简单,注入多个 IFileProvider 即可:
services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\\test1"));
services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\\test2"));
services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\\test3"));
代码修改为:
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设置静态文件目录,即可:
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/
设置好之后,就可以访问项目以外的路径了。
如在IIS部署的时候 ,可以直接忽略IIS中的虚拟目录设置,完完全全可以通过注入的配置来设置达到“虚拟目录”的效果。
简化配置
为了方便达到真实项目中可以直接使用,那么就要设置为可配置的。
在 appsettings.json 中设置:
{"Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"}},"AllowedHosts": "*","VirtualPath": [{"RealPath": "F:\\test1", //真实路径"RequestPath": "/test","Alias": "first"},{"RealPath": "F:\\test2", //真实路径"RequestPath": "/test","Alias": "second"},{"RealPath": "F:\\test3", //真实路径"RequestPath": "/test","Alias": "third"}]
}
创建对应的实体映射:
public class VirtualPathConfig
{public List<PathContent> VirtualPath { get; set; }
}public class PathContent
{public string RealPath { get; set; }public string RequestPath { get; set; }public string Alias { get; set; }
}
在 PhysicalFileProvider 上封装一层,加入别名便于获取:
public class MyFileProvider : PhysicalFileProvider
{public MyFileProvider(string root, string alias) : base(root){this.Alias = alias;}public MyFileProvider(string root, Microsoft.Extensions.FileProviders.Physical.ExclusionFilters filters, string alias) : base(root, filters){this.Alias = alias;}/// <summary>/// 别名/// </summary>public string Alias { get; set; }
}
调整 Startup.ConfigureServices 和 Startup.Configure :
public void ConfigureServices(IServiceCollection services)
{services.AddControllers();services.Configure<VirtualPathConfig>(Configuration);var config = Configuration.Get<VirtualPathConfig>().VirtualPath;config.ForEach(f => {services.AddSingleton(new MyFileProvider(f.RealPath,f.Alias));});
}public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}var config = Configuration.Get<VirtualPathConfig>().VirtualPath;config.ForEach(f =>{app.UseStaticFiles(new StaticFileOptions(){FileProvider = new PhysicalFileProvider(f.RealPath),RequestPath =f.RequestPath});});app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllers();});
}
最后,调整调用方式,即可。
最后
物理文件系统的抽象通过 PhysicalFileProvider 这个 FileProvider 来实现,借助 IFileProvider 的特点,其实可以扩展实现轻量“云盘”的功能了,而不仅仅只是实现IIS虚拟目录功能。搞定,今晚不加班!
Asp.Net Core 中的“虚拟目录”相关推荐
- ASP.NET Core中使用GraphQL - 第七章 Mutation
ASP.NET Core中使用GraphQL - 目录 ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间 ...
- ASP.NET Core中使用GraphQL - 最终章 Data Loader
ASP.NET Core中使用GraphQL - 目录 ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间 ...
- ASP.NET Core 中的静态文件
1.前言 当我们创建Core项目的时候,Web根目录下会有个wwwroot文件目录,wwwroot文件目录里面默认有HTML.CSS.IMG.JavaScript等文件,而这些文件都是Core提供给客 ...
- Asp.net Core中SignalR Core预览版的一些新特性前瞻,附源码(消息订阅与发送二进制数据)
前言 一晃一个月又过去了,上个月有个比较大的项目要验收上线.所以忙的脚不沾地.现在终于可以忙里偷闲,写一篇关于SignalR Core的文章了. 先介绍一下SignalR吧,如下: ASP.NET S ...
- .ASP NET Core中缓存问题案例
本篇博客中,我将描述一个关于会话状态(Session State)的问题, 这个问题我已经被询问了好几次了. 问题的场景 创建一个新的ASP.NET Core应用程序 一个用户在会话状态中设置了一个字 ...
- ASP.NET Core 中文文档 第三章 原理(13)管理应用程序状态
原文:Managing Application State 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:高嵩 在 ASP.NET Core 中,有多种途径可以对应用程序的状态进行 ...
- ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理
ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...
- 在ASP.NET Core中创建自定义端点可视化图
在上篇文章中,我为构建自定义端点可视化图奠定了基础,正如我在第一篇文章中展示的那样.该图显示了端点路由的不同部分:文字值,参数,动词约束和产生结果的端点: 在本文中,我将展示如何通过创建一个自定义的D ...
- 重学ASP.NET Core 中的标记帮助程序
标记帮助程序是什么 标记帮助程序使服务器端代码可以在 Razor 文件中参与创建和呈现 HTML 元素. 例如,内置的 ImageTagHelper 可以将版本号追加到图片名称. 每当图片发生变化时 ...
最新文章
- 前缀函数及kmp算法
- 响应格式html,设置响应格式的HTML邮件
- Could not close the output stream for file hdfs://192.168.190.129:9000/BJ_4.c
- Java中的binarySearch方法
- 第五章 基元类型、引用类型、值类型 CLR学习第五课
- 论文浅尝 - ICML2020 | 对比图神经网络解释器
- 数学趣题——猴子吃桃问题
- MySQL显示连接的数据库名
- 【Tensorflow2】语义分割实战1---斑马线识别
- 【论文视频】对比学习论文综述【论文精读】
- nginx部署前端代码
- 卷积神经网络(CNN)实现手写体识别
- Windows重新分区,解决C盘无法扩展卷
- linux光盘游戏,Linux下五个好玩的即时战略游戏
- 使用跨端解决方案Rax编写鸿蒙应用
- 开机出现 A disk read error occurred Press 时怎么办
- 自己封装的Socket组件,实现服务端多进程共享Socket对象,协同处理客户端请求...
- Vue中的深坑——component和components
- 20221227英语学习
- 星际无限与约瑟企管战略合作 强势开启资本上市之路