跟我一起学.NetCore之静态文件处理的那些事

前言

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

正文

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,默认目录是wwwrootprivate 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即可,可以针对上面说到的每一项进行配置,如下:

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

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

总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307560.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习入门笔记(3)——用梯度下降进行参数更新

首先是对感知器的简单回顾&#xff0c;假设现有的训练集为 D&#xff0c;共有 n 个训练数据&#xff0c;每个数据都有 m 个输入特征和一个输出标签。一个 epoch 就是遍历一次整个训练集&#xff0c;对于每一个训练数据&#xff0c;都计算其预测、计算误差、更新参数。 在一个 e…

ASP.NET Core Blazor Webassembly 之 路由

web最精妙的设计就是通过url把多个页面串联起来&#xff0c;并且可以互相跳转。我们开发系统的时候总是需要使用路由来实现页面间的跳转。传统的web开发主要是使用a标签或者是服务端redirect来跳转。那今天来看看Blazor是如何进行路由的。使用page指定组件的路由path我们可以在…

手撕单例模式(详解)

一:设计模式概述 1:设计模式的概念 软件设计模式&#xff08;Software Design Pattern&#xff09;&#xff0c;又称设计模式&#xff0c;是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题&#xff0…

微软发布.NET 5.0 RC1,未来将只有一个.NET

本周早些时候&#xff0c;微软发布了.NET 5.0 RC1&#xff0c;这是.NET 5 在11 月正式发布之前的第一个“go-live”版本。.NET 5 是.NET 生态系统的统一平台&#xff0c;将所有组件打包成一个跨平台包。新版本包含了.NET Core 3 的很多改进&#xff0c;包括新的语言版本(C# 9 和…

深度学习入门笔记(4)—— Pytorch 和计算图的简单介绍

Pytorch 顾名思义&#xff0c;就是 Torch 7 移植到 Python 的版本&#xff0c;其最大亮点就是自动微分、动态计算图和 Numpy 集成。 Pytorch 相比于 Numpy&#xff0c;优点在于支持 GPU 计算甚至是多设备计算&#xff0c;以及动态计算图。 在 import 的时候&#xff0c;得记住 …

leetcode26. 删除有序数组中的重复项

一:题目 二:上码 // class Solution { // public: // int removeDuplicates(vector<int>& nums) { // //排序 // sort(nums.begin(),nums.end());// //调用unique&#xff08;&#xff09;将vector当中的相同元素 放到 容器的最后面 //…

楼继伟:现有5G技术很不成熟

日前&#xff0c;财政部原部长楼继伟表示&#xff0c;基础设施适度超前是必要的&#xff0c;但有些方面过度超前&#xff0c;抬高了用户成本或不可持续的公共部门债务。现有5G技术很不成熟&#xff0c;数千亿级的投资已经布下&#xff0c;而且运营成本极高&#xff0c;找不到应…

深度学习入门笔记(5)—— Pytorch API 的基本用法框架

第一步&#xff0c;通常是定义我们的神经网络模型。类名后的括号表示我们定义的类会继承 torch.nn.Module&#xff0c;而 super 函数就是调用父类的方法&#xff0c;后面跟 __init__() 就是调用 torch.nn.Module 的构造函数&#xff0c;然后就是我们自定义的模型及其参数。在 f…

跟我一起学.NetCore之路由的最佳实现

前言路由&#xff0c;这词绝对不陌生&#xff0c;不管在前端还是后端都经常提到&#xff0c;而这节不说其他&#xff0c;就聊.NetCore的路由&#xff1b;在之前的Asp.Net MVC 中&#xff0c;路由算是面试时必问的考点&#xff0c;可见其重要性&#xff0c;它的主要作用是映射UR…

leetcode844. 比较含退格的字符串

一:题目 二:上码 class Solution {public:/**思路:1.利用栈 我们将字符串中的单个元素都入栈 当遇到#的时候将将栈顶元素弹出*/bool backspaceCompare(string s, string t) {stack<int> s1;stack<int> s2;for (int i 0; i < s.size(); i) {if(s[i] ! #) s1.pu…

BeetleX之HTTP网关部署

BeetleX组件提供了HTTP网关组件&#xff0c;但使用过程中需要自己写宿主程序来启动它。为了更好的直接使用&#xff0c;组件发布了一个基于.net core 3.1的可运行版本程序并集成了管理插件&#xff1b;只需下载程序即可以在linux或windows下部署一个HTTP网关部署。部署安装运行…

深度学习入门笔记(6)—— Logistic Regression

对比第三节中的 Adaline 和 Logistic Regression&#xff0c;可以发现它们只有两点不同&#xff1a;1、激活函数&#xff0c;Adaline 中的激活函数是恒等函数&#xff08;线性&#xff09;&#xff0c;而 Logistic Regression 中的激活函数是 Sigmoid 函数&#xff08;非线性&a…

微服务模式下,实现前后端多资源服务调用

MicroServices首先&#xff0c;我先解释下&#xff0c;文章标题的意思&#xff1a;咋看起来特别像是一个标题党????&#xff0c;可能是我没想好怎么表达&#xff0c;其实白话文就是&#xff1a;在微服务场景下&#xff0c;肯定会有很多子服务API&#xff0c;那多个前端项目…

leetcode54. 螺旋矩阵(详解)

一:题目 二:上码 class Solution { public:/**思路:1.1 2 3 45 6 7 89 10 11 1213 14 15 162.我们模拟顺时针的顺序,那么得分为4步 上面得一行 (1,2,3)左面得一行 (4,8,12)下面得一行 (16,15,14)右面得一行 (13,9,5)可以看到我们在取数字得时候,我们是每次只取…

深度学习入门笔记(7)—— Multinomial Logistic Regression / Softmax Regression

首先介绍一个非常著名的多分类数据集 MNIST&#xff0c;也就是 0 到 9 的手写数字数据集。每个图像都是 28 * 28&#xff0c;用于Pytorch 数据读取的格式是 NCHW&#xff0c;即 Number、Channel、Height、Weight。 读取图像之后&#xff0c;就能看到一个只有单通道的&#xff0…

[C#.NET 拾遗补漏]09:数据标注与数据校验

数据标注&#xff08;Data Annotation&#xff09;是类或类成员添加上下文信息的一种方式&#xff0c;在 C# 通常用特性&#xff08;Attribute&#xff09;类来描述。它的用途主要可以分为下面这三类&#xff1a;验证 Validation&#xff1a;向数据添加验证规则展现 Display&am…

2023届春招实习拉钩一面凉经

面完就当挂了 老想着其实自己其实还能回答的更好 可回不去了 计网的的ioc七层模型各层的作用 为什么是七层模型而不是两层模型 SpringBoot最核心的注解是什么 Spring中IOC原理以及相关注解 说说对Mysql数据库索引的了解 map有哪些实现 分别讲讲&#xff1f; 项目中数据库…

Pytorch中损失函数 NLLLOSS 和 CROSSENTROPYLOSS 的区别

NLLLOSS 是 negative log likelihood loss 负对数似然损失函数&#xff0c;CROSSENTROPYLOSS 是交叉熵损失函数&#xff0c;它们都是用于多分类任务的损失函数&#xff0c;正如我在笔记中提到的&#xff0c;它们实际上是一样的&#xff0c;在 Pytorch 中这两者的区别就只在于接…

收好这张MySQL导图,全是知识点!

感谢阅读&#xff0c;直接上干货&#xff01;最新整理的MySQL知识点全图&#xff0c;完整系统超3万字。直接跳转文末&#xff0c;下载源文件&#xff01;开源跨平台的.NET Core越来越热门了&#xff0c;腾讯、网易、顺丰等大厂都在招聘&#xff0c;而且都开始明确要求MySQL了&a…

深度学习入门笔记(8)—— Multilayer Perceptron 多层感知器

所谓多层感知器&#xff0c;其实就是具有一个或多个隐藏层&#xff08;hidden layer&#xff09;的全连接前馈神经网络&#xff0c;如图所示&#xff0c;在最重要的求取损失关于权重的偏导数的过程上&#xff0c;跟之前的 Logistic Regression 和 Softmax Regression 一样&…