前言

如今前后端分离开发模式如火如荼,开发职责更加分明(当然前后端一起搞的模式也没有完全褪去);而对于每个公司产品实施来说,部署模式会稍有差别,有的会单独将前端文件部署为一个站点,有的会将前端文件和后端站点整合一起部署;通常当项目规模比较大的时候,分开站点部署是不错的选择,管理和维护清晰,而对于一些小型项目,整合在一起部署为一个站点就显得相对比较方便,毕竟有时候开发是你、部署是你、维护也是你;如果选择整合部署,或者是项目包含静态文件(如图片)的访问,接下来的内容就有用武之地了~~~

正文

Asp.NetCore的请求管道是根据需求通过注册中间件进行构造的(构造过程参考:跟我一起学.NetCore之中间件(Middleware)简介和解析请求管道构建),而通过模板创建出来的项目,请求管道中默认只有关键的几个中间件,如果有其他需要,可以自己添加注册。其中静态文件中间件默认就没有,如下案例:

如上例运行结果,是访问不到添加的index.html,可能有小伙伴会说,那是因为没有加目录,然而并不是这个原因; 现在注册上静态文件中间件试试:

为什么要创建wwwroot目录呢?其他目录不行吗?

当注册静态文件中间件时,通过构造函数可以看出(看下面静态文件中间件的构造函数截图),可以指定对应的静态文件目录,当没有指定目录时,默认就会使用IHostingEnvironment中的WebRootFileProvider,而WebRootFileProvider默认就指定了wwwroot:

在IHostingEnvironment的扩展方法Initialize中指定;

这里就不一一去扒代码了,如果有兴趣的小伙伴,可以按照以下思路去扒:

那如何指定目录,在扒代码的过程中应该会看到,注册中间件的时候可以传参进行指定,如下:

根据需求可以注册多个静态文件中间件,如上所示,请求到请求管道时,会先到wwwroot目录中去找匹配文件,如果找不到继续下一个中间件,去指定的myFile目录中去匹配文件。

往往在开发过程中,会对相关静态文件进行分类,同时Url地址也要不同,通常会通过注册中间件时,将对应静态文件目录映射到指定Url目录,如下:

搞过IIS的小伙伴应该都知道设置默认文件的配置吧,通过现成的中间件也能实现,如下:

注册中间件实现,能减少配置当然也是不错的选择:

到这,小伙伴们应该尝试一下,将wwwroot目录下的index.html的名字改改,再运行一下,同样的访问Url地址肯定访问不了的,如果能,那估计是存在缓存,可以清清缓存再试; 那为什么呢?定位很精确,肯定是默认文件这个中间件再搞事情,来,看看里面咋实现的:

// 定义默认文件中间件
public class DefaultFilesMiddleware
{
// 选项配置
private readonly DefaultFilesOptions _options;
private readonly PathString _matchUrl;
private readonly RequestDelegate _next;
// 静态文件目录读取Provider,默认目录是wwwroot
private readonly IFileProvider _fileProvider;
// 构造函数,用于初始化对应的变量
public DefaultFilesMiddleware(RequestDelegate next, IWebHostEnvironment hostingEnv, IOptions<DefaultFilesOptions> options)
{
// 校验参数
if (next == null)
{
throw new ArgumentNullException(nameof(next));
}
if (hostingEnv == null)
{
throw new ArgumentNullException(nameof(hostingEnv));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
_next = next;
// 初始化配置信息
_options = options.Value;
// 如果没有指定对应的IFileProvider,就用IWebHostEnvironment的WebRootFileProvider,默认目录就wwwroot
_fileProvider = _options.FileProvider ?? Helpers.ResolveFileProvider(hostingEnv);
_matchUrl = _options.RequestPath;
}
// 默认文件中间件的关键方法
public Task Invoke(HttpContext context)
{
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);
// TryMatchPath will make sure subpath always ends with a "/" by adding it if needed.
if (file.Exists)
{
// 如果路径与目录匹配,但没有以斜杠结尾,则重定向以添加斜杠.
// This prevents relative links from breaking.
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 + "/", request.QueryString);
context.Response.Headers[HeaderNames.Location] = redirect;
return Task.CompletedTask;
} // 如果匹配找到,就重写请求地址,由下一个中间件处理,所以在个中间件的注册一定要在UseStaticFiles前面,否则会报错
context.Request.Path = new PathString(context.Request.Path.Value + defaultFile);
break;
}
}
}
}
// 执行下一个中间件
return _next(context);
}
}

在中间件Invoke方法中,遍历_options.DefaultFileNames进行匹配,但我们并没有指定,猜想应该是有默认设置,去看看对应的DefaultFilesOptions:

public DefaultFilesOptions(SharedOptions sharedOptions)
: base(sharedOptions)
{
// 果然,在构造函数中指定了默认列表
DefaultFileNames = new List<string>
{
"default.htm",
"default.html",
"index.htm",
"index.html",
};
}

果然在DefaultFilesOptions的构造函数有对应的默认列表,现在是不是豁然开朗了~~~;那如果一定要指定其他文件怎么办呢?老规矩,注册中间件时传参:

是不是很简单,再来个需求,比如想做一个在线文件管理系统,那肯定得访问目录吧,现在肯定不能访问的,小伙伴们可以试试;

通过注册中间又可以实现,是不是觉得中间件很是灵活,而且还很强大:

这里对于参数的设置就不一一举例了,用法和UseStaticFiles参数差不多一致,小伙伴感兴趣可私下试试。

其实微软早就想到一会要这么干,一会要那么干了,所以直接提供了一个全功能的中间件,直接UseFileServer即可,可以针对上面说到的每一项进行配置,如下:

其实内部就是整合以上说到的中间件,如下源码:

详细配置这里就不一一配置测试了,使用和单独注册中间件时一致,这里只是整合在一起而已。

总结

说好的偏应用,还是没忍住扒代码,但是感觉适当的扒扒能说的更清楚一些;下一节说说路由的最佳实践。

------------------------------------------------

CSDN:Code综艺圈

知乎:Code综艺圈

掘金:Code综艺圈

博客园:Code综艺圈

bilibili:Code综艺圈

------------------------------------------------

一个被程序搞丑的帅小伙,关注"Code综艺圈",识别关注跟我一起学~~~

撸文不易,莫要白瞟,三连走起~~~~

跟我一起学.NetCore之静态文件处理的那些事的更多相关文章

  1. 小白学flask之静态文件

    引入css的方式有两种 1 那在flask中,如何处理静态文件? 做法很简单,只要在你的包或模块旁边创建一个名为 static 的文件夹就行了. flask的静态文件是位于应用的 /static 中的

  2. Django边学边记—静态文件

    概念 项目中的CSS.图片.js都是静态文件 一般会将静态文件放到一个单独的目录中,以方便管理 在html页面中调用时,也需要指定静态文件的路径,Django中提供了一种解析的方式配置静态文件路径 静 ...

  3. 从零开始学JAVA(08)-使用SpringMVC4 Restful 风格引用静态文件 css/js/png

    在写完helloworld后想给网页加点样式(*.css),结果怎么也显示不了,百度了很多种方法后试行尝试,试验成功并记录下来,方便以后查看. 时隔两年,继续学习JAVA,太久没学了,忘记得差不多,还 ...

  4. NetCore入门篇:(五)Net Core项目使用静态文件

    一.简介 1.Net Core默认无法访问静态文件,需要在Startup通过代码添加定义. 2.本文介绍两种静态文件目录实现方式. 二.启用默认目录 1.添加图片文件 2.测试访问结果(不能访问) 3 ...

  5. 跟我一起学.NetCore之中间件(Middleware)简介和解析请求管道构建

    前言 中间件(Middleware)对于Asp.NetCore项目来说,不能说重要,而是不能缺少,因为Asp.NetCore的请求管道就是通过一系列的中间件组成的:在服务器接收到请求之后,请求会经过请 ...

  6. ASP.NET Core 1.1 静态文件、路由、自定义中间件、身份验证简介

    概述 之前写过一篇关于<ASP.NET Core 1.0 静态文件.路由.自定义中间件.身份验证简介>的文章,主要介绍了ASP.NET Core中StaticFile.Middleware ...

  7. Express static 托管静态文件 理解

    今天偶尔看了一下服务端渲染,遇到了express.static, 在以前学习webpack配置服务端渲染时,也使用express.static 中间件,两者配置不太一样,由于当时也没有认真学,所以 一 ...

  8. Django 学习笔记(三) --- HTML 模版加载 css、js、img 静态文件

    人生苦短 ~ Tips:仅适用于 Python 3+(反正差别不大,py2 改改也能用).因为据 Python 之父 Guido van Rossum 说会在 2020 年停止对 Python 2 的 ...

  9. Django 模板 语法 变量 过滤器 模板继承 组件 自定义标签和过滤器 静态文件相关

    本节目录 一 语法 二 变量 三 过滤器 四 标签Tags 五 模板继承 六 组件 七 自定义标签和过滤器 八 静态文件相关 一 语法   模板渲染的官方文档 关于模板渲染你只需要记两种特殊符号(语法 ...

随机推荐

  1. 【异常检测】孤立森林(Isolation Forest)算法简介

    简介 工作的过程中经常会遇到这样一个问题,在构建模型训练数据时,我们很难保证训练数据的纯净度,数据中往往会参杂很多被错误标记噪声数据,而数据的质量决定了最终模型性能的好坏.如果进行人工二次标记,成本会 ...

  2. 笔记:Xshell、更新源、安装软件

    一.Xshell首次连接kali系统中的ssh 1.Xshell :帮助我们去连接各种服务平台,方便管理服务器,链路可以加密处理(ssh/vsftp). 2.步骤: step1:开启kali中的ssh ...

  3. Docker-Docker与IPV6

    公司计划在2020年前完成IPV6化改造,于是我先行查阅了一些资料了解Docker进行IPv6化的可能性. 预计明年正式开始测试. 方法一.使容器中的服务支持IPv6地址 不为容器中的服务特别分配IP ...

  4. 【转】Windows10删除文件时却提示文件不存在的解决方案

    Windows10系统使用一段时间后用户都会定期进行删除清理系统垃圾,减少系统盘的容量占用,但在删除的过程中许多用户都有可能遇到无法删除的情况,如下为删除文件时却提示文件不存在的解决方案. 1.新建一 ...

  5. 实用的git log用法

    git log可以很方便地查看日志,可以根据自己需要,将日志按照特定格式显示,或者输出某种格式. 最原始的输出样式: $ git log commit ca82a6dff817ec66f4434200 ...

  6. 洛谷 P4284 [SHOI2014]概率充电器 概率与期望+换根DP

    洛谷 P4284 [SHOI2014]概率充电器 概率与期望+换根DP 题目描述 著名的电子产品品牌\(SHOI\) 刚刚发布了引领世界潮流的下一代电子产品-- 概率充电器: "采用全新纳米 ...

  7. Java面试题(RabbitMQ篇)

    RabbitMQ 135. rabbitmq 的使用场景有哪些? ①. 跨系统的异步通信,所有需要异步交互的地方都可以使用消息队列.就像我们除了打电话(同步)以外,还需要发短信,发电子邮件(异步)的通 ...

  8. 前端系列-CS与BS的区别

    现在的系统架构有B/S与C/S之分. C/S,即Client/Server(客户端/服务器).我们一般使用的软件架构都是C/S架构,比如各个系统版本中的软件如qq管家.腾讯qq.office等.C/S ...

  9. Spring整合WebSocket

    WebSocket,干什么用的?我们有了HTTP,为什么还要用WebSocket?很多同学都会有这样的疑问.我们先来看一个场景,大家的手机里都有微信,在微信中,只要有新的消息,这个联系人的前面就会有一 ...

  10. WPF实现的加载动画

    2020-09-03 09:43:30 xaml代码 <Grid x:Name="LayoutRoot" Background="Transparent" ...