Asp.Net Core 中的“虚拟目录”实现
写在前面
现在部署Asp.NetCore应用已经不再限制于Windows的IIS上,更多的是Docker容器、各种反向代理来部署。也有少部分用IIS部署的,IIS部署确实是又快又简单,图形化操作三下五除二就可以发布好一个系统了。在过去Asp.NetMVC项目部署的时候,还常常使用IIS一个功能——虚拟目录。
虚拟目录可以直接定位到非项目的其他路径,将路径作为网站的一部分,可实现上传文件保存到其他盘符或间接的使用项目以外的静态文件。在Asp.NetMVC中从虚拟路径中存取文件也很简单,如Server.MapPath("~/Upload/liohuang.jpg");
但在Asp.NetCore上不同,它被抽象出一个“文件系统”,也就是FileProvider。FileProvider是对所有实现了IFileProvider接口的所有类型以及对应对象的统称,在Artech蒋老师的《.NETCore的文件系统[2]:FileProvider是个什么东西?》文章中已经透析了,这里不在罗里吧嗦了。
这篇文章要解决的内容是:Asp.NetCore应用中,如何优雅的使用“虚拟目录”。
实操
首先,新建一个.NetCoreWebApi空项目部署在D盘,“虚拟目录”假设物理路径在F盘,分别创建三个测试目录:F:/test1、F:/test2和F:/test3,目录里分别存放对应的文件1/2/3.jpg和mybook.txt。
读取虚拟目录文件
在Startup.ConfigureServices注入IFileProvider:
services.AddSingleton(newPhysicalFileProvider("F:\\test1"));
新建一个控制器,读取mybook.txt中的内容:
[ApiController] [Route("[controller]/[action]")] publicclassLioHuangController:ControllerBase { [HttpGet] publicobjectGetFiles([FromServices]IFileProviderfileProvider) { varfile=fileProvider.GetFileInfo("mybook.txt"); if(file.Exists) { returnReadTxtContent(file.PhysicalPath); } return0; } //////读取文本(原文地址:https://www.cnblogs.com/EminemJK/p/13362368.html) /// privatestringReadTxtContent(stringPath) { if(!System.IO.File.Exists(Path)) { return"Notfound!"; } using(StreamReadersr=newStreamReader(Path,Encoding.UTF8)) { StringBuildersb=newStringBuilder(); stringcontent; while((content=sr.ReadLine())!=null) { sb.Append(content); } returnsb.ToString(); } } }
访问接口,接口读取文件之后,返回内容:
IFileProvider接口采用目录来组织文件,并统一使用IFileInfo接口来表示,PhysicalPath表示文件的物理路径。
publicinterfaceIFileInfo { boolExists{get;} boolIsDirectory{get;} DateTimeOffsetLastModified{get;} stringName{get;} stringPhysicalPath{get;} StreamCreateReadStream(); }
如多个虚拟目录,怎么处理?简单,注入多个IFileProvider即可,
services.AddSingleton(newPhysicalFileProvider("F:\\test1")); services.AddSingleton (newPhysicalFileProvider("F:\\test2")); services.AddSingleton (newPhysicalFileProvider("F:\\test3"));
代码修改为:
publicobjectGetFiles([FromServices]IEnumerablefileProviders)
IEnumerable
另外,有的说直接ReadTxtContent("F:\test1\mybook.txt");不香吗?香,Asp.NetCore的访问权限要比Asp.NetMVC之前老版本项目要高许多,确实是可以直接读取项目以外的文件,但是并不适合直接去访问,除非说你只有一个地方使用到,那么就可以直接读取,但静态的文件的访问,就访问不到了,仅仅是后台读取而已。所以统一使用IFileProvider来约束,代码的可维护性要高许多。
静态文件访问
在Startup.Configure设置静态文件目录,即可:
app.UseStaticFiles(newStaticFileOptions() { FileProvider=newPhysicalFileProvider("F:\\test1"), RequestPath="/test" });; app.UseStaticFiles(newStaticFileOptions() { FileProvider=newPhysicalFileProvider("F:\\test2"), RequestPath="/test" }); app.UseStaticFiles(newStaticFileOptions() { FileProvider=newPhysicalFileProvider("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" } ] }
创建对应的实体映射:
publicclassVirtualPathConfig { publicListVirtualPath{get;set;} } publicclassPathContent { publicstringRealPath{get;set;} publicstringRequestPath{get;set;} publicstringAlias{get;set;} }
在PhysicalFileProvider上封装一层,加入别名便于获取:
publicclassMyFileProvider:PhysicalFileProvider { publicMyFileProvider(stringroot,stringalias):base(root) { this.Alias=alias; } publicMyFileProvider(stringroot,Microsoft.Extensions.FileProviders.Physical.ExclusionFiltersfilters,stringalias):base(root,filters) { this.Alias=alias; } //////别名 /// publicstringAlias{get;set;} }
调整Startup.ConfigureServices和Startup.Configure:
publicvoidConfigureServices(IServiceCollectionservices) { services.AddControllers(); services.Configure(Configuration); varconfig=Configuration.Get ().VirtualPath; config.ForEach(f=> { services.AddSingleton(newMyFileProvider(f.RealPath,f.Alias)); }); } publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv) { if(env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } varconfig=Configuration.Get ().VirtualPath; config.ForEach(f=> { app.UseStaticFiles(newStaticFileOptions() { FileProvider=newPhysicalFileProvider(f.RealPath), RequestPath=f.RequestPath }); }); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints=> { endpoints.MapControllers(); }); }
最后,调整调用方式,即可。
[HttpGet] publicobjectGetFiles([FromServices]IEnumerablefileProviders) { varfile=fileProviders.FirstOrDefault(x=>x.Alias=="first").GetFileInfo("mybook.txt"); if(file.Exists) { returnReadTxtContent(file.PhysicalPath); } return0; }
最后
物理文件系统的抽象通过PhysicalFileProvider这个FileProvider来实现,借助IFileProvider的特点,其实可以扩展实现轻量“云盘”的功能了,而不仅仅只是实现IIS虚拟目录功能。搞定,今晚不加班!
到此这篇关于Asp.NetCore中的“虚拟目录”实现的文章就介绍到这了,更多相关Asp.NetCore虚拟目录内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。