1批狐、簡(jiǎn)介
當(dāng)我們需要訪問一個(gè)文件或者圖片的,其實(shí)是沒必要經(jīng)過Mvc中間件的處理扇售,完全可以自定義一個(gè)中間件處理,同樣微軟也提供了很多與靜態(tài)文件相關(guān)的中間件。
首先在.NetCore中wwwroot是默認(rèn)的靜態(tài)文件夾承冰。如果想要改變他,需要在Program類中做修改:
// 3.1版本
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
// 設(shè)置靜態(tài)文件夾為根目錄下的staticfile文件夾
webBuilder.UseWebRoot("staticfile");
webBuilder.UseStartup<Startup>();
});
2华弓、UseDirectoryBrowser()中間件
利用UseDirectoryBrowser()實(shí)現(xiàn)目錄瀏覽功能:
首先我們?cè)趙wroot中創(chuàng)建一個(gè)目錄images,然后在
UseDirectoryBrowser()中間件,可以實(shí)現(xiàn)目錄瀏覽的功能困乒,但是在使用該功能之前是需要注入服務(wù)的因此:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
// 注入目錄瀏覽服務(wù)
services.AddDirectoryBrowser();
}
使用中間件:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// 使用目錄瀏覽中間件
app.UseDirectoryBrowser();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
這樣啟動(dòng)就可以看到我wwwroot目錄下的文件夾:
如果我只想顯示wwwroot目錄下的images文件夾該怎么辦呢寂屏?
第一種方式:在Program中指定靜態(tài)文件夾目錄(簡(jiǎn)介中)
第二種方式:UseDirectoryBrowser()也提供了參數(shù),來看一下參數(shù):
- FileProvider: 文件提供者,一般給絕對(duì)路徑(防止在不同系統(tǒng)出錯(cuò))顶燕。
- RequestPath: 提供一個(gè)虛擬路徑 (假如賦值為"/files")就需要訪問該url凑保。
- Formatter: 這個(gè)參數(shù)可以自定義顯示的頁面(布局)請(qǐng)求頭等信息。
使用一下前兩個(gè)參數(shù):
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
// 只展示 wwwroot/images 下的文件
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
// 給一個(gè)虛擬路徑
RequestPath = "/staticfiles"
});
此時(shí)啟動(dòng)程序輸入輸入:http://localhost:5000/staticfiles/ 會(huì)看到改目錄下的文件:
自定義顯示頁面:
新創(chuàng)建一個(gè)類繼承IDirectoryFormatter接口:
只用實(shí)現(xiàn)GenerateContentAsync方法即可,傳遞了兩個(gè)參數(shù)一個(gè)是HttpContext,另一個(gè)是IEnumerable存放的是改目錄下的文件信息,給了這倆參數(shù)涌攻,返回什么信息都是你自己說了算欧引。
例如這里只展示文件名(當(dāng)然你可以定義一個(gè)更好看的頁面):
public class StaticFilesDirectoryFormatter : IDirectoryFormatter
{
public async Task GenerateContentAsync(HttpContext context, IEnumerable<IFileInfo> contents)
{
// 指定返回的是一個(gè)html
// context.Response.ContentType = "text/html;charset=utf-8";
foreach (var item in contents)
{
await context.Response.WriteAsync(item.Name);
}
}
}
并且在使用該中間件的地方給Formatter參數(shù)賦值就可以了:
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/staticfiles",
// 默認(rèn)定義的頁面是在HtmlDirectoryFormatter(HtmlEncoder.Default)中。
Formatter = new StaticFilesDirectoryFormatter()
});
啟動(dòng)查看頁面:
由于自定義頁面很low,所以我就使用默認(rèn)的把恳谎。
使用默認(rèn)的點(diǎn)擊一下圖片你會(huì)發(fā)現(xiàn)是404頁面芝此,沒有找到該文件。
這是因?yàn)橹唤o了瀏覽目錄的權(quán)限因痛,如果還需要可以瀏覽圖片婚苹,需要使用UseStaticFiles()中間件。
3鸵膏、UseStaticFiles()中間件
當(dāng)我們添加添加UseStaticFiles()中間件后膊升,訪問發(fā)現(xiàn)還是404,那是因?yàn)槟J(rèn)還是在wwwroot中查找該文件,自然沒有找到谭企,所以我們需要和UseDirectoryBrowser()中配置一樣廓译。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/staticfiles",
// 默認(rèn)定義的頁面是在HtmlDirectoryFormatter(HtmlEncoder.Default)中。
// Formatter = new StaticFilesDirectoryFormatter()
});
app.UseStaticFiles(new StaticFileOptions
{
RequestPath = "/staticfiles",
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
你會(huì)發(fā)現(xiàn)你可以預(yù)覽圖片了债查。
還有其他的屬性:
- ContentTypeProvider:文件提供器
- OnPrepareResponse:訪問文件走的方法,可以做一些處理
- DefaultContentType:設(shè)置默認(rèn)的MIME訪問類型
- ServeUnknownFileTypes:bool值非区,也就是不認(rèn)可的文件類型提不提供服務(wù)(比如存在.log文件,如果不設(shè)置為true,就無法訪問)盹廷,默認(rèn)false
- httpsCompression:控制HTTPS請(qǐng)求的響應(yīng)壓縮征绸。
在這里只對(duì)ContentTypeProvider和OnPrepareResponse做一下示例:
通過OnPrepareResponse對(duì)jpg圖片進(jìn)行緩存,其他則不進(jìn)行緩存:
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
RequestPath = "/staticfiles",
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
OnPrepareResponse = opr => {
string extion = Path.GetExtension(HttpUtility.UrlDecode(opr.Context.Request.Path));
if (extion == ".jpg")
{
// 設(shè)置緩存
opr.Context.Response.Headers.Add("Cache-Control", "public,max-age=600");
// 也可以進(jìn)行下載
// opr.Context.Response.ContentType = "application/octet-stream";
}
}
}) ;
通過ContentTypeProvider移除對(duì)png圖片的訪問權(quán)限(當(dāng)我們使用ContentTypeProvider移除一中文件訪問權(quán)的話,需要把ServeUnknownFileTypes設(shè)置為false,否者不起作用),對(duì)log結(jié)尾的進(jìn)行下載俄占。
var fileProvider = new FileExtensionContentTypeProvider();
fileProvider.Mappings.Remove(".png");
fileProvider.Mappings[".log"] = "application/octet-stream";
app.UseStaticFiles(new StaticFileOptions
{
ContentTypeProvider = fileProvider,
//ServeUnknownFileTypes = true,
RequestPath = "/staticfiles",
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
OnPrepareResponse = opr => {
string extion = Path.GetExtension(HttpUtility.UrlDecode(opr.Context.Request.Path));
if (extion == ".jpg")
{
// 設(shè)置緩存
opr.Context.Response.Headers.Add("Cache-Control", "public,max-age=600");
// 也可以進(jìn)行下載
// opr.Context.Response.ContentType = "application/octet-stream";
}
},
});
4管怠、UseDefaultFiles()中間件
該中間件可以在啟動(dòng)的時(shí)候顯示html頁面,當(dāng)然也可以給與一個(gè)虛擬路徑缸榄。
UseDefaultFiles()中間件的使用需要在UseStaticFiles()之前,UseDefaultFiles()中間件是嘗試去尋找默認(rèn)文件,
而UseDefaultFiles()沒有尋找到是會(huì)報(bào)錯(cuò)404的渤弛。并且UseDefaultFiles中的參數(shù)有:
- FileProvider:文件的路徑
- RequestPath:虛擬路徑
- DefaultFileNames:是一個(gè)數(shù)組,本身默認(rèn)的文件有defalt.html,defalt.htm,index.html,index.htm,如果你是其他名字需要自己添加碰凶。
其中FileProvider和RequestPath屬性是需要和UseStaticFiles()的屬性保持一致暮芭,否者就會(huì)找不到文件。
例如:
app.UseDefaultFiles(new DefaultFilesOptions {
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/staticfiles",
DefaultFileNames = new List<string> { "aaa.html" }
});
app.UseStaticFiles(new StaticFileOptions {
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/staticfiles",
});
此時(shí)訪問/staticfiles頁面如果有aaa.html頁面欲低,就會(huì)顯示html頁面辕宏,這里就不再演示。
綜上上面的三個(gè)中間件,如果我需要改修一個(gè)RequestPath屬性砾莱,那么其他都要修改瑞筐,并且是重復(fù)的代碼。
于是就有了UseFileServer()中間件腊瑟。這一個(gè)就夠了聚假。
5、UseFileServer()中間件
使用這一個(gè)中間件就相當(dāng)于使用了上面三個(gè)中間件闰非,當(dāng)然功能可就就少一些膘格。
- EnableDefaultFiles:bool值 是否開啟默認(rèn)文件訪問
- EnableDirectoryBrowsing:bool值 是否開啟瀏覽文件夾
- FileProvider:路徑
- RequestPath:虛擬路徑
例如:
app.UseFileServer(new FileServerOptions
{
EnableDefaultFiles = true,
EnableDirectoryBrowsing = true,
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/staticfiles"
});