Javascript 如何解压缩(解压缩)NodeJS 请求的模块 gzip 响应正文?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12148948/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:13:43  来源:igfitidea点击:

How do I ungzip (decompress) a NodeJS request's module gzip response body?

javascriptnode.jsexpresszlib

提问by izk

How do I unzip a gzipped body in a request's module response?

如何在请求的模块响应中解压缩 gzip 压缩的正文?

I have tried several examples around the web but none of them appear to work.

我在网上尝试了几个例子,但似乎没有一个有效。

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

采纳答案by WearyMonkey

I couldn't get request to work either, so ended up using http instead.

我也无法请求工作,所以最终使用 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);
});

回答by Iftah

try adding encoding: nullto the options you pass to request, this will avoid converting the downloaded body to a string and keep it in a binary buffer.

尝试添加encoding: null到您传递给的选项request,这将避免将下载的正文转换为字符串并将其保存在二进制缓冲区中。

回答by Andrew Homeyer

Like @Iftah said, set encoding: null.

就像@Iftah 说的,设置encoding: null.

Full example (less error handling):

完整示例(较少的错误处理):

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

回答by Sai Teja

Actually request module handles the gzip response. In order to tell the request module to decode the body argument in the callback function, We have to set the 'gzip' to true in the options. Let me explain you with an example.

实际上请求模块处理 gzip 响应。为了告诉请求模块解码回调函数中的 body 参数,我们必须在选项中将 'gzip' 设置为 true。让我用一个例子来解释你。

Example:

例子:

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

Note: The data you get on 'reponse' event is not decoded.

注意:您在 'reponse' 事件中获得的数据不会被解码。

This works for me. Hope it works for you guys too.

这对我有用。希望它也适用于你们。

The similar problem usually we ran into while working with request module is with JSON parsing. Let me explain it. If u want request module to automatically parse the body and provide you JSON content in the body argument. Then you have to set 'json' to true in the options.

我们在使用 request 模块时通常遇到的类似问题是 JSON 解析。让我解释一下。如果您希望请求模块自动解析正文并在正文参数中为您提供 JSON 内容。然后你必须在选项中将 '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
})

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

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

回答by Francisco Carriedo Scher

As seen in https://gist.github.com/miguelmota/9946206:

https://gist.github.com/miguelmota/9946206 所示

Both request and request-promise handle it out of the box as of Dec 2017:

截至 2017 年 12 月,请求和请求承诺都开箱即用:

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

回答by samwize

I have formulated a more complete answerafter trying the different ways to gunzip, and solving errors to do with encoding.

在尝试了不同的 gunzip 方法并解决了与编码有关的错误后,我制定了一个更完整的答案

Hope this helps you too:

希望这对你也有帮助:

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

});

回答by Mark Robson

Here is my two cents worth. I had the same problem and found a cool library called concat-stream:

这是我的两分钱。我遇到了同样的问题,发现了一个很酷的库,名为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());
  }));

回答by user764155

Here's a working example (using the request module for node) that gunzips the response

这是一个对响应进行压缩的工作示例(使用节点的请求模块)

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

Full code: https://gist.github.com/0xPr0xy/5002984

完整代码:https: //gist.github.com/0xPr0xy/5002984

回答by Sindre Sorhus

With got, a requestalternative, you can simply do:

使用gotrequest替代方案,您可以简单地执行以下操作:

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

Decompression is handled automagically when needed.

需要时自动处理解压。