AspNetCore(三)-静态文件

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/ 会看到改目录下的文件:

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"
            });

你可能感兴趣的:(AspNetCore(三)-静态文件)