我发现js中的请求模块无法正确处理gzip或inflate格式的http响应。
例如:
request({url:'some url'}, function (error, response, body) {
//if the content-encoding is gzip, the body param here contains binaries other than readable string. And even worse after you convert the body to buffer, u even can not gunzip it.
}
所以我想在官方文档中使用示例代码。
var request = http.get({ host: 'izs.me',
path: '/',
port: 80,
headers: { 'accept-encoding': 'gzip,deflate' } });
request.on('response', function(response) {
var output = fs.createWriteStream('izs.me_index.html');
switch (response.headers['content-encoding']) {
// or, just use zlib.createUnzip() to handle both cases
case 'gzip':
response.pipe(zlib.createGunzip()).pipe(output);
break;
case 'deflate':
response.pipe(zlib.createInflate()).pipe(output);
break;
default:
response.pipe(output);
break;
}
});
问题是代码是将网页写入文件,我希望它可以将页面写入字符串,以便我可以处理页面。我找不到像'StringStream'这样的类。
如果有人对此有任何想法,那就太棒了。
答案 0 :(得分:18)
将响应传递给gzip流,并像使用原始响应对象一样使用它。
var req = http.request(options, function(res) {
var body = "";
res.on('error', function(err) {
next(err);
});
var output;
if( res.headers['content-encoding'] == 'gzip' ) {
var gzip = zlib.createGunzip();
res.pipe(gzip);
output = gzip;
} else {
output = res;
}
output.on('data', function (data) {
data = data.toString('utf-8');
body += data;
});
output.on('end', function() {
return next(false, body);
});
});
req.on('error', function(err) {
next(err);
})
答案 1 :(得分:6)
简化示例:
var https = require('https');
var gunzip = require('zlib').createGunzip();
var options = {
host: 'api.stackexchange.com',
path: '/2.1/info?site=stackoverflow'
};
https.get(options, function(res) {
var body = '';
res.pipe(gunzip);
gunzip.on('data', function (data) {
body += data;
});
gunzip.on('end', function() {
console.log(JSON.parse(body));
});
});
答案 2 :(得分:3)
我遇到了类似的问题,想继续使用request
库而不是内置的http模块。我在这里讨论了两种工作方法:http://nickfishman.com/post/49533681471/nodejs-http-requests-with-gzip-deflate-compression。其中一个类似于@Teemu的答案,而另一个使用流。
答案 3 :(得分:3)
请求模块处理gzip响应。我们所要做的就是设置' gzip'选项中的属性。有关详细说明,请访问以下linke。在那里,我已经用例子清楚地解释过了。
答案 4 :(得分:1)
在utf-8编码的情况下,@ Dawid和@Teemu的答案有时会在答案中制造字符。这段代码效果更好:
function getGzipped(url, cb) {
// downloads gzipped file
http.get(url, function(res) {
let chunks = [];
res.on('data', function(chunk) {
chunks.push(chunk);
});
res.on('end', function() {
let buffer = Buffer.concat(chunks);
zlib.gunzip(buffer, function(err, decoded) {
if (err) throw err;
cb(decoded && decoded.toString());
});
});
});
}