1、简介
当我们需要访问一个文件或者图片的,其实是没必要经过Mvc中间件的处理,完全可以自定义一个中间件处理,同样微软也提供了很多与静态文件相关的中间件。
首先在.NetCore中wwwroot是默认的静态文件夹。如果想要改变他,需要在Program类中做修改:
// 3.1版本
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
// 设置静态文件夹为根目录下的staticfile文件夹
webBuilder.UseWebRoot("staticfile");
webBuilder.UseStartup();
});
2、UseDirectoryBrowser()中间件
利用UseDirectoryBrowser()实现目录浏览功能:
首先我们在wwroot中创建一个目录images,然后在
UseDirectoryBrowser()中间件,可以实现目录浏览的功能,但是在使用该功能之前是需要注入服务的因此:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
// 注入目录浏览服务
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?}");
});
}
这样启动就可以看到我wwwroot目录下的文件夹:
如果我只想显示wwwroot目录下的images文件夹该怎么办呢?
第一种方式:在Program中指定静态文件夹目录(简介中)
第二种方式:UseDirectoryBrowser()也提供了参数,来看一下参数:
- FileProvider: 文件提供者,一般给绝对路径(防止在不同系统出错)。
- RequestPath: 提供一个虚拟路径 (假如赋值为"/files")就需要访问该url。
- Formatter: 这个参数可以自定义显示的页面(布局)请求头等信息。
使用一下前两个参数:
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
// 只展示 wwwroot/images 下的文件
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
// 给一个虚拟路径
RequestPath = "/staticfiles"
});
此时启动程序输入输入:http://localhost:5000/staticfiles/ 会看到改目录下的文件:
自定义显示页面:
新创建一个类继承IDirectoryFormatter接口:
只用实现GenerateContentAsync方法即可,传递了两个参数一个是HttpContext,另一个是IEnumerable存放的是改目录下的文件信息,给了这俩参数,返回什么信息都是你自己说了算。
例如这里只展示文件名(当然你可以定义一个更好看的页面):
public class StaticFilesDirectoryFormatter : IDirectoryFormatter
{
public async Task GenerateContentAsync(HttpContext context, IEnumerable contents)
{
// 指定返回的是一个html
// context.Response.ContentType = "text/html;charset=utf-8";
foreach (var item in contents)
{
await context.Response.WriteAsync(item.Name);
}
}
}
并且在使用该中间件的地方给Formatter参数赋值就可以了:
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/staticfiles",
// 默认定义的页面是在HtmlDirectoryFormatter(HtmlEncoder.Default)中。
Formatter = new StaticFilesDirectoryFormatter()
});
启动查看页面:
由于自定义页面很low,所以我就使用默认的把。
使用默认的点击一下图片你会发现是404页面,没有找到该文件。
这是因为只给了浏览目录的权限,如果还需要可以浏览图片,需要使用UseStaticFiles()中间件。
3、UseStaticFiles()中间件
当我们添加添加UseStaticFiles()中间件后,访问发现还是404,那是因为默认还是在wwwroot中查找该文件,自然没有找到,所以我们需要和UseDirectoryBrowser()中配置一样。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/staticfiles",
// 默认定义的页面是在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?}");
});
}
你会发现你可以预览图片了。
还有其他的属性:
- ContentTypeProvider:文件提供器
- OnPrepareResponse:访问文件走的方法,可以做一些处理
- DefaultContentType:设置默认的MIME访问类型
- ServeUnknownFileTypes:bool值,也就是不认可的文件类型提不提供服务(比如存在.log文件,如果不设置为true,就无法访问),默认false
- httpsCompression:控制HTTPS请求的响应压缩。
在这里只对ContentTypeProvider和OnPrepareResponse做一下示例:
通过OnPrepareResponse对jpg图片进行缓存,其他则不进行缓存:
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")
{
// 设置缓存
opr.Context.Response.Headers.Add("Cache-Control", "public,max-age=600");
// 也可以进行下载
// opr.Context.Response.ContentType = "application/octet-stream";
}
}
}) ;
通过ContentTypeProvider移除对png图片的访问权限(当我们使用ContentTypeProvider移除一中文件访问权的话,需要把ServeUnknownFileTypes设置为false,否者不起作用),对log结尾的进行下载。
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")
{
// 设置缓存
opr.Context.Response.Headers.Add("Cache-Control", "public,max-age=600");
// 也可以进行下载
// opr.Context.Response.ContentType = "application/octet-stream";
}
},
});
4、UseDefaultFiles()中间件
该中间件可以在启动的时候显示html页面,当然也可以给与一个虚拟路径。
UseDefaultFiles()中间件的使用需要在UseStaticFiles()之前,UseDefaultFiles()中间件是尝试去寻找默认文件,
而UseDefaultFiles()没有寻找到是会报错404的。并且UseDefaultFiles中的参数有:
- FileProvider:文件的路径
- RequestPath:虚拟路径
- DefaultFileNames:是一个数组,本身默认的文件有defalt.html,defalt.htm,index.html,index.htm,如果你是其他名字需要自己添加。
其中FileProvider和RequestPath属性是需要和UseStaticFiles()的属性保持一致,否者就会找不到文件。
例如:
app.UseDefaultFiles(new DefaultFilesOptions {
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/staticfiles",
DefaultFileNames = new List { "aaa.html" }
});
app.UseStaticFiles(new StaticFileOptions {
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/staticfiles",
});
此时访问/staticfiles页面如果有aaa.html页面,就会显示html页面,这里就不再演示。
综上上面的三个中间件,如果我需要改修一个RequestPath属性,那么其他都要修改,并且是重复的代码。
于是就有了UseFileServer()中间件。这一个就够了。
5、UseFileServer()中间件
使用这一个中间件就相当于使用了上面三个中间件,当然功能可就就少一些。
- EnableDefaultFiles:bool值 是否开启默认文件访问
- EnableDirectoryBrowsing:bool值 是否开启浏览文件夹
- FileProvider:路径
- RequestPath:虚拟路径
例如:
app.UseFileServer(new FileServerOptions
{
EnableDefaultFiles = true,
EnableDirectoryBrowsing = true,
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images")),
RequestPath = "/staticfiles"
});