Nodejs中用zlib解压gzip

Nodejs中用zlib解压gzip

为了减少网络传输数据量,http传输过程中会采用通用的压缩算法来压缩数据,gzip属于最常用的压缩算法。

使用node的http模块发送请求时并没有帮我们进行解压,因此我们需要手动去判断gzip。

var http = require('http');
var options = {
 hostname: 'www.qq.com',
 port: 80,
 method: 'get',
 headers: {
  'Accept-Encoding': 'gzip'
 }
}

http.request(options, handler);

function handler(responder) { // do something }

我们设置http头Accept-Encoding为gzip告诉服务器我们支持gzip压缩,服务器收到请求后,返回responder头中content-encoding带有gzip表明返回的数据为gzip压缩过的内容,node中可以通过responder.headers[‘content-encoding’]来判断服务器返回内容是否gzip压缩过。

function handler(responder) {
 if(responder.headers['content-encoding'].indexOf('gzip') != -1) {
  // 解压gzip
 }
}

已经可以判断服务器返回的是gzip压缩过的内容,接下来我们需要去解压,幸好node提供了zlib模块。

我们用zlib模块来解压gzip

var zlib = require('zlib');
var fs = require('fs');
var gunzipStream = zlib.createGunzip();
var toWrite = fs.createWriteStream('qq.html');

zlib.createGunzip是一个transform流,通过pipe我们可以很方便解压gzip

function handler(responder) {
 if(responder.headers['content-encoding'].indexOf('gzip') != -1) {
  responder.pipe(gunzipStream).pipe(toWrite);
 }
}

若是要让服务端支持gzip压缩可以先判断请求头的accept-encoding是否含有gzip

var fs = require('fs');
var http = require('http');
var zlib = require('zlib');

http.createServer(function(req, res) { var file = fs.createReadStream(’./qq.html’); var acceptEncoding = req.headers[‘accept-encoding’]; if(acceptEncoding && acceptEncoding.indexOf(‘gzip’) != -1) { var gzipStream = zlib.createGzip(); // 设置返回头content-encoding为gzip res.writeHead(200, { “content-encoding”: “gzip” }); file.pipe(gzipStream).pipe(res); } else { res.writeHead(200); // 不压缩 file.pipe(res); } }).listen(8080);

使用curl测试一下

# 不带有Accept-Encoding:gzip 返回正常文本
curl localhost:8080
# 带Accept-Encoding:gzip 返回压缩过的文件
curl -H "Accept-Encoding:gzip" localhost:8080

通过zlib可以实现客户端和服务端对gzip的压缩和解压

在express中提供了compress的中间件用来处理gzip

引用自 nodejs中用zlib解压gzip


5 回复

在Node.js中,使用zlib模块可以帮助我们轻松地处理gzip压缩的数据。以下是如何在Node.js中使用zlib模块解压gzip压缩的数据的详细步骤和示例代码。

客户端请求并解压gzip

首先,我们创建一个HTTP请求,并设置请求头以告知服务器我们支持gzip压缩。如果服务器返回的数据是gzip压缩的,我们可以使用zlib模块中的createGunzip()方法来解压数据。

const http = require('http');
const zlib = require('zlib');
const fs = require('fs');

const options = {
  hostname: 'www.qq.com',
  port: 80,
  method: 'GET',
  headers: {
    'Accept-Encoding': 'gzip'
  }
};

http.request(options, (res) => {
  const encoding = res.headers['content-encoding'];

  if (encoding && encoding.includes('gzip')) {
    console.log('Server returned gzip compressed data.');
    
    // 创建解压流
    const gunzipStream = zlib.createGunzip();
    
    // 创建写入流,用于将解压后的数据写入文件
    const toWrite = fs.createWriteStream('qq_uncompressed.html');
    
    // 将响应数据通过管道传递给解压流,再将解压后的数据写入文件
    res.pipe(gunzipStream).pipe(toWrite);
  } else {
    console.log('Server returned uncompressed data.');
    // 处理未压缩的数据
    res.pipe(fs.createWriteStream('qq.html'));
  }
}).end();

服务端提供gzip压缩的数据

同样地,服务端也可以根据客户端的请求头来决定是否压缩返回的数据。以下是一个简单的HTTP服务器示例:

const http = require('http');
const fs = require('fs');
const zlib = require('zlib');

http.createServer((req, res) => {
  const acceptEncoding = req.headers['accept-encoding'] || '';

  if (acceptEncoding.includes('gzip')) {
    console.log('Client accepts gzip encoded response.');

    // 设置返回头为gzip压缩
    res.writeHead(200, { 'Content-Encoding': 'gzip' });

    // 读取文件并创建gzip压缩流
    const fileStream = fs.createReadStream('./qq.html');
    const gzipStream = zlib.createGzip();

    // 通过管道将文件内容压缩后返回
    fileStream.pipe(gzipStream).pipe(res);
  } else {
    console.log('Client does not accept gzip encoded response.');

    // 直接返回未压缩的文件内容
    res.writeHead(200, {});
    fs.createReadStream('./qq.html').pipe(res);
  }
}).listen(8080, () => {
  console.log('Server listening on port 8080');
});

以上代码展示了如何在Node.js中使用zlib模块进行gzip的压缩与解压操作。通过这种方式,我们可以有效地减少网络传输的数据量,提高传输效率。


handler 中:应为 if (responder.headers[“content-encoding”] && responder.headers[‘content-encoding’].indexOf(‘gzip’) != -1) 不然没有压缩时会报错

在Node.js中使用zlib模块解压gzip压缩的数据是一种常见的需求。以下是具体的步骤和代码示例,以帮助理解如何实现这一点。

示例代码

客户端(解压响应)

const http = require('http');
const zlib = require('zlib');
const fs = require('fs');

const options = {
    hostname: 'www.qq.com',
    port: 80,
    path: '/',
    method: 'GET',
    headers: {
        'Accept-Encoding': 'gzip'
    }
};

const request = http.request(options, (response) => {
    const contentEncoding = response.headers['content-encoding'];

    if (contentEncoding && contentEncoding.includes('gzip')) {
        const gunzip = zlib.createGunzip();
        const writeStream = fs.createWriteStream('uncompressed.html');

        response.pipe(gunzip).pipe(writeStream);

        writeStream.on('finish', () => {
            console.log('文件已成功写入并解压缩');
        });
    } else {
        const data = [];
        response.on('data', (chunk) => {
            data.push(chunk);
        });

        response.on('end', () => {
            const buffer = Buffer.concat(data);
            console.log('响应已接收到,但未被gzip压缩');
        });
    }
});

request.end();

服务端(压缩响应)

const http = require('http');
const zlib = require('zlib');
const fs = require('fs');

http.createServer((req, res) => {
    const acceptEncoding = req.headers['accept-encoding'];

    if (acceptEncoding && acceptEncoding.includes('gzip')) {
        const fileStream = fs.createReadStream('./qq.html');
        const gzipStream = zlib.createGzip();

        res.writeHead(200, { 'Content-Encoding': 'gzip' });
        fileStream.pipe(gzipStream).pipe(res);
    } else {
        const fileStream = fs.createReadStream('./qq.html');
        res.writeHead(200);
        fileStream.pipe(res);
    }
}).listen(8080, () => {
    console.log('Server is running on port 8080');
});

说明

  1. 客户端

    • 发送HTTP GET请求到指定的URL,并指定Accept-Encoding: gzip
    • 检查响应头中的Content-Encoding是否包含gzip
    • 如果是gzip压缩的,则使用zlib.createGunzip()创建一个解压缩流,然后将响应流传递给该解压缩流,最后将解压缩后的数据写入文件。
  2. 服务端

    • 监听8080端口,并处理所有传入的请求。
    • 检查请求头中的Accept-Encoding是否包含gzip
    • 如果请求头中包含gzip,则读取本地文件并使用zlib.createGzip()创建一个压缩流,将文件内容压缩后发送回客户端。
    • 否则,直接将文件内容发送回客户端而不进行任何压缩。

以上就是如何使用Node.js的zlib模块来处理gzip压缩和解压缩的基本方法。

回到顶部