Как распаковать (распаковать) тело ответа модуля gzip запроса NodeJS?
как распаковать тело gzipped в ответе модуля запроса?
Я пробовал несколько примеров в интернете, но ни один из них не работает.
request(url, function(err, response, body) {
if(err) {
handleError(err)
} else {
if(response.headers['content-encoding'] == 'gzip') {
// How can I unzip the gzipped string body variable?
// For instance, this url:
// http://highsnobiety.com/2012/08/25/norse-projects-fall-2012-lookbook/
// Throws error:
// { [Error: incorrect header check] errno: -3, code: 'Z_DATA_ERROR' }
// Yet, browser displays page fine and debugger shows its gzipped
// And unzipped by browser fine...
if(response.headers['content-encoding'] && response.headers['content-encoding'].toLowerCase().indexOf('gzip') > -1) {
var body = response.body;
zlib.gunzip(response.body, function(error, data) {
if(!error) {
response.body = data.toString();
} else {
console.log('Error unzipping:');
console.log(error);
response.body = body;
}
});
}
}
}
}
9 ответов:
Я также не мог получить запрос на работу, поэтому вместо этого использовал http.
var http = require("http"), zlib = require("zlib"); function getGzipped(url, callback) { // buffer to store the streamed decompression var buffer = []; http.get(url, function(res) { // pipe the response into the gunzip to decompress var gunzip = zlib.createGunzip(); res.pipe(gunzip); gunzip.on('data', function(data) { // decompression chunk ready, add it to the buffer buffer.push(data.toString()) }).on("end", function() { // response and decompression complete, join the buffer and return callback(null, buffer.join("")); }).on("error", function(e) { callback(e); }) }).on('error', function(e) { callback(e) }); } getGzipped(url, function(err, data) { console.log(data); });
попробуйте добавить
encoding: null
к параметрам, которые вы передаете вrequest
, Это позволит избежать преобразования загруженного тела в строку и сохранить его в двоичном буфере.
Как сказал @Iftah, set
encoding: null
.полный пример (обработки ошибок):
request = require('request'); zlib = require('zlib'); request(url, {encoding: null}, function(err, response, body){ if(response.headers['content-encoding'] == 'gzip'){ zlib.gunzip(body, function(err, dezipped) { callback(dezipped.toString()); }); } else { callback(body); } });
фактически модуль запроса обрабатывает ответ gzip. Чтобы сообщить модулю запроса декодировать аргумент body в функции обратного вызова, мы должны установить 'gzip' в true в параметрах. Позвольте мне объяснить вам на примере.
пример:
var opts = { uri: 'some uri which return gzip data', gzip: true } request(opts, function (err, res, body) { // now body and res.body both will contain decoded content. })
Примечание: данные, которые вы получаете на' reponse ' событие не декодируется.
это работает для меня. Надеюсь, это сработает и для вас, ребята.
С подобной проблемой мы обычно сталкивались во время работы модуль запроса с разбором JSON. Позвольте мне объяснить это. Если вы хотите, чтобы модуль запроса автоматически анализировал тело и предоставлял вам содержимое JSON в аргументе body. Затем вы должны установить 'json' в true в настройках.
var opts = { uri:'some uri that provides json data', json: true } request(opts, function (err, res, body) { // body and res.body will contain json content })
Ссылка:https://www.npmjs.com/package/request#requestoptions-callback
я сформулировал еще полный ответ после попытки различных способов gunzip и решения ошибок, связанных с кодированием.
надеюсь, что это поможет вам тоже:
var request = require('request'); var zlib = require('zlib'); var options = { url: 'http://some.endpoint.com/api/', headers: { 'X-some-headers' : 'Some headers', 'Accept-Encoding' : 'gzip, deflate', }, encoding: null }; request.get(options, function (error, response, body) { if (!error && response.statusCode == 200) { // If response is gzip, unzip first var encoding = response.headers['content-encoding'] if (encoding && encoding.indexOf('gzip') >= 0) { zlib.gunzip(body, function(err, dezipped) { var json_string = dezipped.toString('utf-8'); var json = JSON.parse(json_string); // Process the json.. }); } else { // Response is not gzipped } } });
вот рабочий пример (используя модуль запроса для узла), который gunzips ответ
function gunzipJSON(response){ var gunzip = zlib.createGunzip(); var json = ""; gunzip.on('data', function(data){ json += data.toString(); }); gunzip.on('end', function(){ parseJSON(json); }); response.pipe(gunzip); }
полный код:https://gist.github.com/0xPr0xy/5002984
вот мои два цента стоит. У меня была та же проблема, и я нашел классную библиотеку под названием
concat-stream
:let request = require('request'); const zlib = require('zlib'); const concat = require('concat-stream'); request(url) .pipe(zlib.createGunzip()) .pipe(concat(stringBuffer => { console.log(stringBuffer.toString()); }));
Как видно в https://gist.github.com/miguelmota/9946206:
как запрос, так и запрос-обещание обрабатывают его из коробки по состоянию на декабрь 2017 года:
var request = require('request') request( { method: 'GET' , uri: 'http://www.google.com' , gzip: true } , function (error, response, body) { // body is the decompressed response body console.log('server encoded the data as: ' + (response.headers['content-encoding'] || 'identity')) console.log('the decoded data is: ' + body) } )
С
got
, arequest
альтернативы, вы можете просто сделать:got(url).then(response => { console.log(response.body); });
декомпрессия обрабатывается автоматически, когда это необходимо.