浅谈ASP.NET Core静态文件处理源码探究(5)

这个操作相对简单了许多,主要就是判断请求路径能否和预设置的路径匹配的到,如果匹配到则获取可以操作当前目录内容IDirectoryContents然后通过IDirectoryFormatter输出如何展示目录内容,关于IDirectoryFormatter的默认实现类HtmlDirectoryFormatter这里就不展示里面的代码了,逻辑非常的加单就是拼接成table的html代码然后输出,有兴趣的同学可自行查看源码[点击查看HtmlDirectoryFormatter源码],如果自定义的话规则也非常简单,主要看你想输出啥

public class TreeDirectoryFormatter: IDirectoryFormatter { public Task GenerateContentAsync(HttpContext context, IEnumerable<IFileInfo> contents) { //遍历contents实现你想展示的方式 } }

然后在UseDirectoryBrowser的时候给Formatter赋值即可

app.UseDirectoryBrowser(new DirectoryBrowserOptions { Formatter = new TreeDirectoryFormatter() });

UseDefaultFiles

很多时候出于安全考虑或者其他原因我们想在访问某个目录的时候返回一个默认的页面或展示,这个事实我们就需要使用UseDefaultFiles中间件,当我们配置了这个中间件,如果命中了配置路径,那么会直接返回默认的页面信息,简单使用方式如下

//wwwroot目录访问展示默认文件 app.UseDefaultFiles(); //或自定义目录默认展示文件 var fileProvider = new PhysicalFileProvider($"{env.ContentRootPath}/staticfiles"); app.UseDefaultFiles(new DefaultFilesOptions { RequestPath = "/staticfiles", FileProvider = fileProvider });

老规矩,我们查看下注册UseDefaultFiles的源码[点击查看DefaultFilesExtensions源码]

public static class DefaultFilesExtensions { public static IApplicationBuilder UseDefaultFiles(this IApplicationBuilder app) { return app.UseMiddleware<DefaultFilesMiddleware>(); } public static IApplicationBuilder UseDefaultFiles(this IApplicationBuilder app, string requestPath) { return app.UseDefaultFiles(new DefaultFilesOptions { RequestPath = new PathString(requestPath) }); } public static IApplicationBuilder UseDefaultFiles(this IApplicationBuilder app, DefaultFilesOptions options) { return app.UseMiddleware<DefaultFilesMiddleware>(Options.Create(options)); } }

使用方式和UseStaticFiles、UseDirectoryBrowser是一样,最终都是调用传递DefaultFilesOptions的方法,我们查看一下DefaultFilesOptions的大致实现[点击查看源码]

public class DefaultFilesOptions : SharedOptionsBase { public DefaultFilesOptions() : this(new SharedOptions()) { } public DefaultFilesOptions(SharedOptions sharedOptions) : base(sharedOptions) { //系统提供的默认页面的名称 DefaultFileNames = new List<string> { "default.htm", "default.html", "index.htm", "index.html", }; } /// <summary> /// 通过这个属性可以配置默认文件名称 /// </summary> public IList<string> DefaultFileNames { get; set; } }

和之前的方法如出一辙,都是继承自SharedOptionsBase,通过DefaultFileNames我们可以配置默认文件的名称,默认是default.html/htm和index.html/htm。我们直接查看中间件DefaultFilesMiddleware的源码[点击查看源码]

public class DefaultFilesMiddleware { private readonly DefaultFilesOptions _options; private readonly PathString _matchUrl; private readonly RequestDelegate _next; private readonly IFileProvider _fileProvider; public DefaultFilesMiddleware(RequestDelegate next, IWebHostEnvironment hostingEnv, IOptions<DefaultFilesOptions> options) { _next = next; _options = options.Value; _fileProvider = _options.FileProvider ?? Helpers.ResolveFileProvider(hostingEnv); _matchUrl = _options.RequestPath; } public Task Invoke(HttpContext context) { //1.我们使用UseDefaultFiles中间件的时候要置于UseRouting之上,否则就会不生效 //2.IsGetOrHeadMethod判断请求为Get或Head的情况下才生效 //3.TryMatchPath判断请求的路径和设置的路径是否可以匹配的上 if (context.GetEndpoint() == null && Helpers.IsGetOrHeadMethod(context.Request.Method) && Helpers.TryMatchPath(context, _matchUrl, forDirectory: true, subpath: out var subpath)) { //根据匹配路径获取物理路径对应的信息 var dirContents = _fileProvider.GetDirectoryContents(subpath.Value); if (dirContents.Exists) { //循环配置的默认文件名称 for (int matchIndex = 0; matchIndex < _options.DefaultFileNames.Count; matchIndex++) { string defaultFile = _options.DefaultFileNames[matchIndex]; //匹配配置的启用默认文件的路径+遍历到的默认文件名称的路径是否存在 var file = _fileProvider.GetFileInfo(subpath.Value + defaultFile); if (file.Exists) { //判断请求路径是否已"https://www.jb51.net/"结尾,如果不是则从定向(这个点个人感觉可以改进) if (!Helpers.PathEndsInSlash(context.Request.Path)) { context.Response.StatusCode = StatusCodes.Status301MovedPermanently; var request = context.Request; var redirect = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path + "https://www.jb51.net/", request.QueryString); context.Response.Headers[HeaderNames.Location] = redirect; return Task.CompletedTask; } //如果匹配的上,则将配置的启用默认文件的路径+遍历到的默认文件名称的路径组合成新的Path交给_next(context) //比如将组成类似这种路径/staticfiles/index.html向下传递 context.Request.Path = new PathString(context.Request.Path.Value + defaultFile); break; } } } } return _next(context); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/02e386c850b617c8edb815e6797b27eb.html