webentwicklung-frage-antwort-db.com.de

Wie kann ich den gzip-Antworttext eines NodeJS-Anforderungsmoduls entpacken (dekomprimieren)?

Wie entpacke ich einen gezippten Text in der Antwort eines Anforderungsmoduls?

Ich habe verschiedene Beispiele im Internet ausprobiert, aber keines davon scheint zu funktionieren.

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;
                    }
                });
            }
        }
    }
}
62
izk

Ich konnte auch keine Arbeitsanforderung erhalten und habe stattdessen http verwendet.

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);
});
51
WearyMonkey

fügen Sie encoding: null zu den Optionen hinzu, die Sie an request übergeben. Dadurch wird vermieden, dass der heruntergeladene Text in eine Zeichenfolge konvertiert und in einem Binärpuffer gespeichert wird.

34
Iftah

Wie @Iftah sagte, setze encoding: null.

Vollständiges Beispiel (weniger Fehlerbehandlung):

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);
    }
});
27
Andrew Homeyer

Das Anforderungsmodul behandelt tatsächlich die gzip-Antwort. Damit das Anforderungsmodul das body-Argument in der Rückruffunktion dekodieren kann, muss in den Optionen 'gzip' auf true gesetzt werden. Lassen Sie sich von mir anhand eines Beispiels erläutern.

Beispiel:

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.
})

Hinweis: Die Daten, die Sie bei einem Antwortereignis erhalten, werden nicht decodiert.

Das funktioniert bei mir. Hoffe, es funktioniert auch für euch.

Das ähnliche Problem, auf das wir normalerweise beim Arbeiten mit dem Anforderungsmodul gestoßen sind, ist das Parsing mit JSON. Lass es mich erklären. Wenn Sie möchten, dass das Anforderungsmodul den Hauptteil automatisch analysiert und Ihnen JSON-Inhalte im Hauptteilargument zur Verfügung stellt. Dann müssen Sie in den Optionen 'json' auf true setzen.

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
})

Referenz: https://www.npmjs.com/package/request#requestoptions-callback

26
Sai Teja

Aus https://Gist.github.com/miguelmota/9946206 :

Sowohl Anfrage als auch Anforderungsversprechen sind ab Dezember 2017 sofort einsatzbereit:

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)
    }
  )

Ich habe eine mehr vollständige Antwort formuliert, nachdem ich die verschiedenen Möglichkeiten zum Gunzip ausprobiert und Fehler im Zusammenhang mit der Codierung behoben habe.

Hoffe das hilft dir auch:

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
    }
  }

});
4
samwize

Hier sind meine zwei Cent wert. Ich hatte das gleiche Problem und fand eine coole Bibliothek namens 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());
  }));
3
Mark Robson

Hier ist ein funktionierendes Beispiel (unter Verwendung des Anforderungsmoduls für Knoten), das die Antwort komprimiert

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);
}

Vollständiger Code: https://Gist.github.com/0xPr0xy/5002984

3
user764155

Mit got , einer request Alternative, können Sie einfach Folgendes tun:

got(url).then(response => {
    console.log(response.body);
});

Die Dekomprimierung wird bei Bedarf automatisch durchgeführt.

1
Sindre Sorhus