前言
上次,我們實現了根據 subpath
特定格式《動態設置靜態文件存儲目錄》。
例如:
subpath | 靜態文件路徑 |
---|---|
/userAId/1.jpg | c:\abc\userAId\1.jpg |
/userBId/1.jpg | d:\xyz\123\userBId\1.jpg |
但是,如果 subpath
不能有這種特定格式,只能用通用格式,比如https://<hostname>/StaticFiles/images/1.jpg
。
怎么實現?
思路
請求上下文肯定包含了信息能夠區分出用戶,比如 Session/Cookie、二級域名等,可以通過它來反向映射出靜態文件路徑。
例如:
二級域名 | 靜態文件路徑 |
---|---|
a.mycompany.com | c:\abc\ |
b.mycompany.com | d:\xyz\123 |
在 IFileProvider
接口實現中,我們獲取不到當前請求上下文,但是中間件可以。
查看 UseStaticFiles
源代碼,它使用的是 StaticFileMiddleware
中間件:
public?static?IApplicationBuilder?UseStaticFiles(this?IApplicationBuilder?app,?StaticFileOptions?options)
{...return?app.UseMiddleware<StaticFileMiddleware>(Options.Create(options));
}
查看 StaticFileMiddleware
源代碼[1],它的關鍵實現是這個TryServeStaticFile
方法:
public?class?StaticFileMiddleware
{...private?Task?TryServeStaticFile(HttpContext?context,?string??contentType,?PathString?subPath){var?fileContext?=?new?StaticFileContext(context,?_options,?_logger,?
_fileProvider,?contentType,?subPath);if?(!fileContext.LookupFileInfo()){_logger.FileNotFound(fileContext.SubPath);}else{//?If?we?get?here,?we?can?try?to?serve?the?filereturn?fileContext.ServeStaticFile(context,?_next);}return?_next(context);}
}
具體如何獲取靜態文件是依賴_fileProvider
,因此,我們只需要替換 _fileProvider
,換成根據請求上下文獲取對應?PhysicalFileProvider
的方法即可。
實現
創建 MyIOStaticFileMiddleware
,復制 StaticFileMiddleware
的原始代碼,僅僅修改 TryServeStaticFile
方法:
public?class?MyIOStaticFileMiddleware
{...private?Task?TryServeStaticFile(HttpContext?context,?string??contentType,?PathString?subPath){var?fileContext?=?new?StaticFileContext(context,?_options,?_logger,?
GetPhysicalFileProvider(context),?contentType,?subPath);...return?_next(context);}
}
然后根據 context
獲取對應的 PhysicalFileProvider
進行處理:
private?IFileProvider?GetPhysicalFileProvider(HttpContext?context)
{//實際可從數據庫獲取if?(context.Request.Host.Host.StartsWith("a.mycompany.com")){return?new?PhysicalFileProvider(@"c:\abc");}if?(context.Request.Host.Host.StartsWith("b.mycompany.com")){return?new?PhysicalFileProvider(@"d:\xyz\123");}...
}
使用
按如下方式配置靜態文件中間件:
app.UseMiddleware<MyIOStaticFileMiddleware>();
運行效果如圖:
結論
今天,我們通過自定義 StaticFileMiddleware
,實現了根據請求上下文動態設置靜態文件存儲目錄。
想了解更多內容,請關注我的個人公眾號”My IO“
參考資料
[1]
源代碼: https://github.com/dotnet/aspnetcore/blob/main/src/Middleware/StaticFiles/src/StaticFileMiddleware.cs