Asp.Net Core 中的“虛擬目錄”實(shí)現(xiàn)
寫在前面
現(xiàn)在部署Asp.Net Core應(yīng)用已經(jīng)不再限制于Windows的IIS上,更多的是Docker容器、各種反向代理來部署。也有少部分用IIS部署的,IIS部署確實(shí)是又快又簡單,圖形化操作三下五除二就可以發(fā)布好一個(gè)系統(tǒng)了。在過去Asp.Net MVC 項(xiàng)目部署的時(shí)候,還常常使用IIS一個(gè)功能——虛擬目錄。

虛擬目錄可以直接定位到非項(xiàng)目的其他路徑,將路徑作為網(wǎng)站的一部分,可實(shí)現(xiàn)上傳文件保存到其他盤符或間接的使用項(xiàng)目以外的靜態(tài)文件。在Asp.Net MVC中從虛擬路徑中存取文件也很簡單,如Server.MapPath("~/Upload/liohuang.jpg");
但在Asp.Net Core上不同,它被抽象出一個(gè)“文件系統(tǒng)”,也就是FileProvider。FileProvider是對(duì)所有實(shí)現(xiàn)了IFileProvider接口的所有類型以及對(duì)應(yīng)對(duì)象的統(tǒng)稱,在Artech蔣老師的《.NET Core的文件系統(tǒng)[2]:FileProvider是個(gè)什么東西?》文章中已經(jīng)透析了,這里不在羅里吧嗦了。
這篇文章要解決的內(nèi)容是:Asp.Net Core應(yīng)用中,如何優(yōu)雅的使用“虛擬目錄”。
實(shí)操
首先,新建一個(gè).Net Core WebApi空項(xiàng)目部署在D盤,“虛擬目錄”假設(shè)物理路徑在F盤,分別創(chuàng)建三個(gè)測試目錄:F:/test1、F:/test2和F:/test3,目錄里分別存放對(duì)應(yīng)的文件1/2/3.jpg和mybook.txt。
讀取虛擬目錄文件
在Startup.ConfigureServices注入IFileProvider:
services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\\test1"));
新建一個(gè)控制器,讀取mybook.txt中的內(nèi)容:
[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>
/// 讀取文本 (原文地址:https://www.cnblogs.com/EminemJK/p/13362368.html)
/// </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();
}
}
}
訪問接口,接口讀取文件之后,返回內(nèi)容:

IFileProvider接口采用目錄來組織文件,并統(tǒng)一使用IFileInfo接口來表示,PhysicalPath表示文件的物理路徑。
public interface IFileInfo
{
bool Exists { get; }
bool IsDirectory { get; }
DateTimeOffset LastModified { get; }
string Name { get; }
string PhysicalPath { get; }
Stream CreateReadStream();
}
如多個(gè)虛擬目錄,怎么處理?簡單,注入多個(gè)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接口數(shù)組將會(huì)有三個(gè),按注入的順序?qū)?yīng)不同的目錄。當(dāng)然,注入IFileProvider的時(shí)候,就可以封裝一層了,下面再講。
另外,有的說直接ReadTxtContent("F:\test1\mybook.txt");不香嗎?香,Asp.Net Core的訪問權(quán)限要比Asp.Net MVC之前老版本項(xiàng)目要高許多,確實(shí)是可以直接讀取項(xiàng)目以外的文件,但是并不適合直接去訪問,除非說你只有一個(gè)地方使用到,那么就可以直接讀取,但靜態(tài)的文件的訪問,就訪問不到了,僅僅是后臺(tái)讀取而已。所以統(tǒng)一使用IFileProvider來約束,代碼的可維護(hù)性要高許多。
靜態(tài)文件訪問
在Startup.Configure設(shè)置靜態(tài)文件目錄,即可:
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同上面所說的,設(shè)置好物理路徑的根目錄,RequestPath則是訪問路徑的前綴,必須是斜桿“/”開頭,訪問地址前綴則為:https://localhost:5001/test/。設(shè)置好之后,就可以訪問項(xiàng)目以外的路徑了。



如在IIS部署的時(shí)候 ,可以直接忽略IIS中的虛擬目錄設(shè)置,完完全全可以通過注入的配置來設(shè)置達(dá)到“虛擬目錄”的效果。
簡化配置
為了方便達(dá)到真實(shí)項(xiàng)目中可以直接使用,那么就要設(shè)置為可配置的:
在appsettings.json中設(shè)置:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"VirtualPath": [
{
"RealPath": "F:\\test1", //真實(shí)路徑
"RequestPath": "/test",
"Alias": "first"
},
{
"RealPath": "F:\\test2", //真實(shí)路徑
"RequestPath": "/test",
"Alias": "second"
},
{
"RealPath": "F:\\test3", //真實(shí)路徑
"RequestPath": "/test",
"Alias": "third"
}
]
}
創(chuàng)建對(duì)應(yīng)的實(shí)體映射:
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上封裝一層,加入別名便于獲?。?/p>
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; }
}
調(diào)整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();
});
}
最后,調(diào)整調(diào)用方式,即可。
[HttpGet]
public object GetFiles([FromServices] IEnumerable<MyFileProvider> fileProviders)
{
var file = fileProviders.FirstOrDefault(x=>x.Alias=="first").GetFileInfo("mybook.txt");
if (file.Exists)
{
return ReadTxtContent(file.PhysicalPath);
}
return 0;
}
最后
物理文件系統(tǒng)的抽象通過PhysicalFileProvider這個(gè)FileProvider來實(shí)現(xiàn),借助IFileProvider的特點(diǎn),其實(shí)可以擴(kuò)展實(shí)現(xiàn)輕量“云盤”的功能了,而不僅僅只是實(shí)現(xiàn)IIS虛擬目錄功能。搞定,今晚不加班!
到此這篇關(guān)于Asp.Net Core 中的“虛擬目錄”實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Asp.Net Core 虛擬目錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
ASP.NET中iframe框架點(diǎn)擊左邊頁面鏈接 右邊顯示鏈接頁面內(nèi)容
這篇文章主要介紹了ASP.NET中iframe框架點(diǎn)擊左邊頁面鏈接,右邊顯示鏈接頁面內(nèi)容的實(shí)現(xiàn)代碼,感興趣的小伙伴們可以參考一下2016-07-07
Asp.net回調(diào)技術(shù)Callback學(xué)習(xí)筆記
這篇文章主要記錄了Asp.net回調(diào)技術(shù)Callback的一些知識(shí),感興趣的朋友可以參考下2014-08-08
.NET Core 2.0如何生成圖片驗(yàn)證碼完整實(shí)例
這篇文章主要給大家介紹了關(guān)于.NET Core 2.0如何生成圖片驗(yàn)證碼的相關(guān)資料,該功能主要是利用ZKWeb.System.Drawing來實(shí)現(xiàn),文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
ASP.NET中實(shí)現(xiàn)中文簡/繁體自動(dòng)轉(zhuǎn)換的類
這篇文章主要介紹了ASP.NET中實(shí)現(xiàn)中文簡/繁體自動(dòng)轉(zhuǎn)換的類,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2006-09-09
.net調(diào)用JScript腳本及JS url加密解密
.net調(diào)用JScript腳本及JS url加密解密,需要的朋友可以參考一下2013-03-03
ASP.NET Core使用JWT自定義角色并實(shí)現(xiàn)策略授權(quán)需要的接口
這篇文章介紹了ASP.NET Core使用JWT自定義角色并實(shí)現(xiàn)策略授權(quán)需要的接口,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01
ASP.NET第一次訪問慢的完美解決方案(MVC,Web Api)
這篇文章主要給大家介紹了關(guān)于ASP.NET第一次訪問慢的完美解決方案(MVC,Web Api)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用ASP.NET具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07

