手写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"); } }
内容版权声明:除非注明,否则皆为本站原创文章。