手写Node静态资源服务器的实现方法(2)
- gzip方法用于实现压缩
- gunzip方法用于实现解压
- 其中文件msg.txt是同级目录
- 为什么需要这么写:gzip(path.join(__dirname,'msg.txt'));
- 因为console.log(process.cwd());打印出当前工作目录是根目录,并不是文件所在目录,如果这么写gzip('msg.txt');找不到文件就会报错
- basename 从一个路径中得到文件名,包括扩展名的,可以传一个扩展名参数,去掉扩展名
- extname 获取扩展名
- 压缩的格式和解压的格式需要对上,否则会报错
有些时候我们拿到的字符串不是一个流,那怎么解决呢
let zlib=require('zlib');
let str='hello';
zlib.gzip(str,(err,buffer)=>{
console.log(buffer.length);
zlib.unzip(buffer,(err,data)=>{
console.log(data.toString());
})
});
有可能压缩后的内容比原来还大,要是内容太少的话,压缩也没什么意义了
文本压缩的效果会好一点,因为有规律
在http中应用压缩和解压
下面实现这样一个功能,如图:

客户端向服务器发起请求的时候,会通过accept-encoding(比如:Accept-Encoding:gzip,default)告诉服务器我支持的解压缩的格式
- 服务器端需要根据Accept-Encoding显示的格式进行压缩,没有的格式就不能压缩,因为浏览器无法解压
- 如果客户端需要的Accept-Encoding中的格式服务端没有,也无法实现压缩
let http = require("http");
let path = require("path");
let url = require("url");
let zlib = require("zlib");
let fs = require("fs");
let { promisify } = require("util");
let mime = require("mime");
//把一个异步方法转成一个返回promise的方法
let stat = promisify(fs.stat);
http.createServer(request).listen(8080);
async function request(req, res) {
let { pathname } = url.parse(req.url);
let filepath = path.join(__dirname, pathname);
// fs.stat(filepath,(err,stat)=>{});现在不这么写了,异步的处理起来比较麻烦
try {
let statObj = await stat(filepath);
res.setHeader("Content-Type", mime.getType(pathname));
let acceptEncoding = req.headers["accept-encoding"];
if (acceptEncoding) {
if (acceptEncoding.match(/\bgzip\b/)) {
res.setHeader("Content-Encoding", "gzip");
fs
.createReadStream(filepath)
.pipe(zlib.createGzip())
.pipe(res);
} else if (acceptEncoding.match(/\bdeflate\b/)) {
res.setHeader("Content-Encoding", "deflate");
fs
.createReadStream(filepath)
.pipe(zlib.createDeflate())
.pipe(res);
} else {
fs.createReadStream(filepath).pipe(res);
}
} else {
fs.createReadStream(filepath).pipe(res);
}
} catch (e) {
res.statusCode = 404;
res.end("Not Found");
}
}
内容版权声明:除非注明,否则皆为本站原创文章。

