Comment décompresser (décompresser) le corps de réponse gzip du module D'une requête NodeJS?
Comment décompresser un corps gzippé dans la réponse du module d'une requête?
J'ai essayé plusieurs exemples sur le web mais aucun d'entre eux ne semble fonctionner.
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 réponses
Je n'ai pas pu faire fonctionner la requête non plus, donc j'ai fini par Utiliser http à la place.
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);
});
Essayez d'Ajouter encoding: null
aux options que vous passez à request
, cela évitera de convertir le corps téléchargé en chaîne et de le conserver dans un tampon binaire.
Comme @ Iftah a dit, set encoding: null
.
Exemple complet (moins de gestion des erreurs):
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);
}
});
En fait, le module request gère la réponse gzip. Afin de dire au module de requête de décoder l'argument body dans la fonction de rappel, nous devons définir le 'gzip' sur true dans les options. Permettez-moi de vous expliquer avec un exemple.
Exemple:
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.
})
Remarque: Les données que vous obtenez sur l'événement' reponse ' ne sont pas décodées.
Cela fonctionne pour moi. J'espère que cela fonctionne pour vous aussi.
Le problème similaire que nous avons généralement rencontré en travaillant avec le module de requête est avec l'analyse JSON. Permettez-moi de l'expliquer. Si vous voulez que le module de requête analyse automatiquement le corps et vous fournisse du contenu JSON dans l'argument body. Ensuite, vous devez définir 'json' sur true dans les options.
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
})
Référence: https://www.npmjs.com/package/request#requestoptions-callback
J'ai formulé une réponse plus complète Après avoir essayé les différentes façons de gunzip, et résolu les erreurs à faire avec l'encodage.
J'espère que cela vous aidera aussi:
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
}
}
});
Voici un exemple de travail (en utilisant le module de requête pour le nœud) qui gunzips la réponse
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);
}
Code Complet: https://gist.github.com/0xPr0xy/5002984
Voici mes deux cents. J'ai eu le même problème et trouvé une belle bibliothèque appelée 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());
}));
Comme dans https://gist.github.com/miguelmota/9946206:
Request et request-promise le gèrent à partir de décembre 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)
}
)
Avec got
, un request
alternative, vous pouvez tout simplement faire:
got(url).then(response => {
console.log(response.body);
});
La décompression est gérée automatiquement en cas de besoin.