xingbofeng.github.io
xingbofeng.github.io copied to clipboard
node gzip
一般情况下Node.js
使用zlib
模块的使用gzip()
压缩,但有一个坏处是,大文件会使V8
缓冲区爆掉,原因是由于gzip()
使用缓存,而V8
的缓存区最大不超过0x3FFFFFFF
字节(约为1GB),一般不使用缓存的方式压缩与解压缩数据,而使用Stream
,原因可见Coding with Streams:
const zlib = require('zlib');
const fs = require('fs');
fs.readFile(__dirname + '/hello.txt', 'utf-8', (readFileErr, readFileData) => {
if (readFileErr) {
return console.error('readFileErr error:' + readFileErr.message);
}
zlib.gzip(readFileData, (gzipErr, gzipData) => {
if (gzipErr) {
return console.error('gzipErr error:' + gzipErr.message);
}
fs.writeFile(__dirname + '/hello.txt.gz', gzipData, (writeFileErr) => {
if (writeFileErr) {
return console.error('writeFile error:' + writeFileErr.message);
}
});
});
});
zlib
模块同样支持gzipSync()
同步方法进行压缩:
const zlib = require('zlib');
const fs = require('fs');
let readFileData;
try {
readFileData = fs.readFileSync(__dirname + '/hello.txt', 'utf-8');
} catch (readFileErr) {
console.error('readFileErr error:' + readFileErr.message);
}
let gzipData;
try {
gzipData = zlib.gzipSync(readFileData);
} catch (gzipErr) {
return console.error('gzipErr error:' + gzipErr.message);
}
try {
fs.writeFileSync(__dirname + '/hello.txt.gz', gzipData);
} catch (writeFileErr) {
return console.error('writeFile error:' + writeFileErr.message);
}
Node.js
使用zlib
模块的createGzip()
创建并返回一个带有给定options
的新的Gzip
对象,通过这种方法,并配合Stream
模块可以实现文件压缩,使用流的好处是可以实现大文件压缩,提升空间效率和时间效率:
const fs = require('fs');
const zlib = require('zlib');
const gzip = zlib.createGzip();
const readableStream = fs.createReadStream('./hello.txt');
const writeableStream = fs.createWriteStream('./hello.txt.gz');
readableStream.pipe(gzip).pipe(writeableStream);
反过来,zlib
模块的createGunzip()
方法可以实现解压缩:
const fs = require('fs');
const zlib = require('zlib');
const gunzip = zlib.createGunzip();
const readableStream = fs.createReadStream('./hello.txt.gz');
const writeableStream = fs.createWriteStream('./hello2.txt');
readableStream.pipe(gunzip).pipe(writeableStream);
要实现高性能的http
服务,可以使用gzip
对返回的静态文件进行压缩,判断HTTP
报文头部是否含有accept-encoding
首部,并且其值为gzip
:
const http = require('http');
const zlib = require('zlib');
const fs = require('fs');
const server = http.createServer((req, res) => {
// 如果HTTP报文头部是否含有Accept-Encoding首部,并且其值为gzip
if (req.headers['accept-encoding'].indexOf('gzip') !== -1) {
// 设定response HTTP报文头部的Content-Encoding首部值为gzip
res.writeHead(200, {
'Content-Encoding': 'gzip',
});
// 在每次请求到来时创建Gzip
const gzip = zlib.createGzip();
return fs.createReadStream(__dirname + '/hello.html').pipe(gzip).pipe(res);
}
return fs.createReadStream(__dirname + '/hello.html').pipe(res);
});
server.listen(80, () => {
console.log('server listen in localhost:80')
});
要在express中使用,则一般使用compression
中间件:
const compression = require('compression');
const express = require('express');
const app = express();
//尽量在其他中间件前使用compression
app.use(compression());