javascript - desde - npm
¿Cómo descomprimo(descomprimo) un cuerpo de respuesta gzip del módulo de la solicitud NodeJS? (9)
¿Cómo descomprimo un cuerpo con gzip en la respuesta de un módulo de solicitud?
He intentado con varios ejemplos en la web, pero ninguno de ellos parece funcionar.
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;
}
});
}
}
}
}
Al igual que @Iftah dijo, establezca la encoding: null
.
Ejemplo completo (menos manejo de errores):
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);
}
});
Aquí está mi valor de dos centavos. Tuve el mismo problema y encontré una biblioteca genial llamada 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());
}));
Aquí hay un ejemplo de trabajo (usando el módulo de solicitud para el nodo) que dispara la respuesta
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);
}
Código completo: https://gist.github.com/0xPr0xy/5002984
Como se ve en https://gist.github.com/miguelmota/9946206 :
Tanto la solicitud como la promesa de la solicitud se manejan fuera de la caja a partir de diciembre de 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)
}
)
Con got
, una alternativa de request
, simplemente puede hacer:
got(url).then(response => {
console.log(response.body);
});
La descompresión se maneja automágicamente cuando es necesario.
En realidad, el módulo de solicitud maneja la respuesta gzip. Para decirle al módulo de solicitud que descodifique el argumento del cuerpo en la función de devolución de llamada, tenemos que configurar el ''gzip'' como verdadero en las opciones. Déjame explicarte con un ejemplo.
Ejemplo:
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.
})
Nota: Los datos que obtienes en el evento ''respuesta'' no se decodifican.
Esto funciona para mí Espero que funcione para ustedes también.
El problema similar que usualmente encontramos al trabajar con el módulo de solicitud es con el análisis JSON. Déjame explicarlo. Si desea que el módulo de solicitud analice automáticamente el cuerpo y le proporcione contenido JSON en el argumento cuerpo. Luego debes establecer ''json'' en verdadero en las opciones.
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
})
Referencia: https://www.npmjs.com/package/request#requestoptions-callback
He formulado una respuesta más completa después de probar las diferentes formas de gunzip y resolver errores relacionados con la codificación.
Espero que esto le ayude también:
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
}
}
});
Tampoco pude obtener una solicitud para trabajar, así que terminé usando http en su lugar.
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);
});
intente agregar encoding: null
a las opciones que pase a request
, esto evitará convertir el cuerpo descargado en una cadena y mantenerlo en un búfer binario.