《DotNet Web应用单文件部署系列》二、打包wwwroot文件夹
在这篇文章中,你将学到web缓存规则,文件传输中用到的压缩格式,以及如何手写代码响应请求。最后还能学到快速打包wwwroot文件夹组件用法。
一、了解Response Header
当第一次加载程序时,浏览器将打开页面并下载所有的资源连接。假如页面没有错误返回都是正确那么就是返回文件数据和Http Status为200 -OK的状态
我们看下这个jquery.min.js文件Http请求对应的Response Header,这里会包含ETag值。HTTP内容如下:
ETag: 1d7a4ae31f17d74
ETag :HTTP响应头是资源的特定版本的标识符。这可以让缓存更高效,并节省带宽,因为如果内容没有改变,Web服务器不需要发送完整的响应。而如果内容发生了变化,使用ETag有助于防止资源的同时更新相互覆盖。如果给定URL中的资源更改,则一定要生成新的Etag值。 因此Etags类似于指纹,也可能被某些服务器用于跟踪。 比较etags能快速确定此资源是否变化,但也可能被跟踪服务器永久存留。
如果再次请求这个地址的话,浏览器将发送ETag到服务端,如果两个值没有变化,那么服务端会发送304状态到浏览器,那么浏览器将使用之前的资源而不是重新下载一份。
If-None-Match: 1d7a4ae31f17d74
将文件都缓存到了客户端,这样就提高了浏览器的响应性能,并且通过304状态,浏览器与服务端的请求流量得以减少。
加快浏览器的响应性能,还可以设置两种方案,
1)减少浏览器与服务端的请求次数;可以在响应头内设置Expires,Cache-Control两个参数。
Expires:响应头包含日期/时间, 即在此时候之后,响应过期。
Cache-Control:通用消息头字段,被用于在http请求和响应中,通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中。
2)压缩文件,减少返回流量,从而提高响应性能。
在HTTP 请求时,客户端会发送Accept-Encoding请求头给服务端,服务端就可以根据Accept-Encoding请求头匹配到压缩方式,将文件压缩后返回。
二、DotNet 5 手写代码响应请求
先放主代码
1 [HttpGet("_/js/jquery.min.js")]
2 public IActionResult __js_jquery_min_js()
3 {
4 if (SetResponseHeaders("4F252523D4AF0B478C810C2547A63E19") == false) { return StatusCode(304); }
5 const string s = "base64编码";
6 var bytes = UseCompressBytes(s);
7 return File(bytes, "text/javascript");
8 }
第一行,我们定义请求方式及请求地址。
第二行,我们将请求地址转成可用的方法名。
第四行,我们设置返回头,如果返回头有相同的ETAG值,就返回304。ETAG值可使用Hash值,如Md5。
第五行,获取文件的base64编码,注意文件先经Brotli 算法压缩,然后转成base64编码的。这样有效地减少文件大小。
第六行,我们尝试以压缩的编码返回。
第七行,我们返回文件内容及Content-Type类型。
SetResponseHeaders方法如下
1 SetResponseHeaders方法如下
2 private bool SetResponseHeaders(string etag)
3 {
4 if (Request.Headers["If-None-Match"] == etag) { return false; }
5 Response.Headers["Cache-Control"] = "max-age=315360000";
6 Response.Headers["Etag"] = etag;
7 Response.Headers["Date"] = DateTime.Now.ToString("r");
8 Response.Headers["Expires"] = DateTime.Now.AddYears(100).ToString("r");
9 return true;
10 }
我们先对比etag值是否相同,如果相同返回false。不同就设置etag值以及过期时间100年有效。
UseCompressBytes方法如下:
1 private byte[] UseCompressBytes(string s)
2 {
3 var bytes = Convert.FromBase64String(s);
4 var sp = Request.Headers["Accept-Encoding"].ToString().Replace(" ", "").ToLower().Split(',');
5 if (sp.Contains("br")) {
6 Response.Headers["Content-Encoding"] = "br";
7 } else {
8 using (MemoryStream stream = new MemoryStream(bytes)) {
9 using (BrotliStream zStream = new BrotliStream(stream, CompressionMode.Decompress)) {
10 using (var resultStream = new MemoryStream()) {
11 zStream.CopyTo(resultStream);
12 bytes = resultStream.ToArray();
13 }
14 }
15 }
16 if (sp.Contains("gzip")) {
17 Response.Headers["Content-Encoding"] = "gzip";
18 using (MemoryStream stream = new MemoryStream()) {
19 using (GZipStream zStream = new GZipStream(stream, CompressionMode.Compress)) {
20 zStream.Write(bytes, 0, bytes.Length);
21 zStream.Close();
22 }
23 bytes = stream.ToArray();
24 }
25 }
26 }
27 return bytes;
28 }
第一步,判断是否支持Brotli 算法压缩,如果支持就马上返回。
第二步,使用Brotli 算法解压。
第三步,判断是否支持gzip算法压缩,如果支持使用gzip算法压缩,然后返回。
第四步,返回原bytes。
三、快速压缩打包wwwroot文件夹
打包wwwroot文件夹很简单,但文件一个一个手写就会觉得很麻烦。这时就需要ToolGood.WwwRoot组件,在Nuget上直接获取。
3.1、快速上手
1)新建一个控制台应用程序,
2)从Nuget上引用ToolGood.WwwRoot组件,
3)添加以下代码
1 WwwRootSetting setting = new WwwRootSetting();
2 setting.NameSpace = "ToolGood.TextFilter.Controllers";
3 setting.InFolderPath = @"你的项目路径\wwwroot";
4 setting.OutFolderPath = @"你的项目路径\Controllers\wwwroot";
5
6 setting.ExcludeFileSuffixs.Add(".old.js");
7 setting.ExcludeFileSuffixs.Add(".map");
8 setting.BuildControllers();
4)运行控制台应用程序,就会生成相应的cs文件。
2.2、WwwRootSetting参数简介
NameSpace参数设置命名空间
InFolderPath参数指定wwwroot目录
OutFolderPath参数指定输出目录
ExcludeFileSuffixs参数依据文件后缀排除文件
ExcludeFiles参数 依据文件排除文件
2.3、其他相关
1)每个生成的文件都有 #if RELEASE 和 #endif,保证调试模式下不会被编译。
2)app.UseStaticFiles();前面添加 #if DEBUG 后面添加 #endif ,保证生成后不会使用本地静态文件。
3)程序更新后,静态文件过期问题。网上有很多成熟的方案,这里介绍一个最简单的方法,使用静态文件+程序版本号来解决,如:
<script src="_/js/ok.js?v=20210911"></script>
后记:
.net 5 单文件运行时会将dll文件释放到内存内,技术高超的人还是能从内存截取dll文件。提高dll文件反编译成本,我们可以将dll文件混淆。
dll文件混淆后会带来一系列问题,主要是操作麻烦,所以下几篇将介绍dll文件混淆、VS调时使用项目源文件,只在生成时使用dll混淆文件。
《DotNet Web应用单文件部署系列》二、打包wwwroot文件夹的更多相关文章
- 《DotNet Web应用单文件部署系列》一、pubxml文件配置
很多人想用DotNet开发软件赚点外快子补添家用,但心里总放不下心来,担心被人破解了.好消息是去年发布的DotNet 5支持单文件部署,不同于DotNet 3运行时将文件释放到临时文件夹内,DotNe ...
- linux内核中的文件描述符(二)--socket和文件描述符
http://blog.csdn.net/ce123_zhouwei/article/details/8459730 Linux内核中的文件描述符(二)--socket和文件描述符 Kernel ve ...
- 《DotNet Web应用单文件部署系列》三、混淆dll文件
众所周知,C#编译后的dll文件可被反编译,网上搜索"C# 反编译"会出现一大堆资料.为了提高反编译成本,我们必须对dll文件进行混淆处理. 目前,C#混淆工具很多,我推荐obfu ...
- C# 文件读写系列二
读取文件原则上非常简单,但它不是通过FileInfo和DirectoryInfo来完成的,关于FileInfo和DirectoryInfo请参考C# 文件操作系列一,在.Net Framework4. ...
- Python小白学习之路(二十)—【打开文件的模式二】【文件的其他操作】
打开文件的模式(二) 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码.图片文件的jgp格 ...
- Windows phone开发之文件夹与文件操作系列(一)文件夹与文件操作
Windows phone7中文件的存储模式是独立的,即独立存储空间(IsolatedStorage).对文件夹与文件操作,需要借助IsolatedStorageFile类. IsolatedStor ...
- ASP.NET Core部署系列二:发布到CentOS上
前言: 在上一节中,通过一系列的步骤,已经将项目部署到IIS上,虽然遇到了一些问题,但最终解决并成功运行了.而在这一节中,将尝试通过linux系统的环境下,部署项目,实现Net Core跨平台的亮点. ...
- web前端知识大纲:系列二 css篇
web前端庞大而复杂的知识体系的组成:html.css和 javascript 二.css 1.CSS选择器 CSS选择器即通过某种规则来匹配相应的标签,并为其设置CSS样式,常用的有类选择器.标签选 ...
- 小白日记40:kali渗透测试之Web渗透-SQL手工注入(二)-读取文件、写入文件、反弹shell
SQL手工注入 1.读取文件[load_file函数] ' union SELECT null,load_file('/etc/passwd')--+ burpsuite 2.写入文件 ' unio ...
随机推荐
- DC-7靶机
仅供个人娱乐 靶机信息 下载地址:http://www.five86.com/downloads/DC-7.zip 一.主机扫描 二.信息收集 或者 python3 cmseek.py --url h ...
- 阿里云RocketMQ定时/延迟消息队列实现
新的阅读体验:http://www.zhouhong.icu/post/157 一.业务需求 需要实现一个提前二十分钟通知用户去做某件事的一个业务,拿到这个业务首先想到的最简单得方法就是使用Redis ...
- FastAPI实战:简易MockServe
Mock 我个人理解就是为了伪造返回结果的东西,MockServe通常说的就是接口未开放完成但是现在需要调用,所以无论是通过转发还是直接访问这个url,其结果基本就是自己定义的 当然做仔细点就是 给个 ...
- 巧用map解决nginx的Location里if失效问题
需求: Nginx根据参数来输出不同的header 我们想用Nginx来判断一些通用的参数, 根据参数情况在输出中不同的header, 或者cookie, 那么根据正常思路, 有如下配置: locat ...
- JMeter(1)-介绍+环境+安装+使用
一.开发接口测试案例的整体方案: 分析出测试需求,并拿到开发提供的接口说明文档: 从接口说明文档中整理出接口测试案例(包括详细的入参和出参数据以及明确的格式和检查点). 和开发一起对评审接口测试案例 ...
- C++ 1//设计立方体类 //创建立方体的类 //设计属性和行为 //获取立方体的面积和体积 //分别利用(全局函数 和 成员函数)判断俩个立方体是否相等
1 //设计立方体类 2 //创建立方体的类 3 //设计属性和行为 4 //获取立方体的面积和体积 5 //分别利用(全局函数 和 成员函数)判断俩个立方体是否相等 6 #include <i ...
- zookeeper查看启动状态报错:Error contacting service. It is probably not running.
问题描述 我有三台虚拟机master.slave1.slave2.每台虚拟机启动zkServer.sh时都没有报错,然后紧接着查看zkServer.sh的状态,这时候出现了错误:Error conta ...
- HTML5(十一)——WebSocket 基础教程
一.为什么要学 WebSocket? websocket 是 HTML5 提供的一种长链接双向通讯协议,使得客户端和服务器之间的数据交换更简单,允许服务端主动向客户端推送数据,并且客户端与服务端只需连 ...
- Java Lambda 表达式源码分析
基本概念 Lambda 表达式 函数式接口 方法引用 深入实现原理 字节码 为什么不使用匿名内部类? invokedynamic 总结 参考链接 GitHub 项目 Lambda 表达式是什么?JVM ...
- HTTP和HTTPS是什么 二者区别是什么
HTTP简介 HTTP(超文本传输协议)是网络上最为广泛的传输协议,被用于在web浏览器和网站服务器之间的传输协议.HTTP是一个简单的请求-响应协议,它通常运行在TCP之上.它指定了客户端可能发送给 ...