【nodejs】http模块请求响应乱码解决

解决和介绍了在Nodejs中使用http模块请求响应时乱码的问题。

【nodejs】http模块请求响应乱码解决

By img Microanswer Create at:Oct 30, 2019, 9:53:01 PM 

Tags: http nodejs 响应乱码

解决和介绍了在Nodejs中使用http模块请求响应时乱码的问题。


重要声明:本文章仅仅代表了作者个人对此观点的理解和表述。读者请查阅时持自己的意见进行讨论。

一、问题重现

在使用nodejs的http模块时,如果请求的页面不是UTF8的编码,那么响应中的中文就会乱码。比如下面的代码就会导致乱码:

let http  = require("http");

http.get("http://www.people.com.cn",response => {

    response.setEncoding("UTF-8");
    let html = "";

    response.on("data", chunk => {
        html += chunk;
    });

    response.on("end", () => {
         console.log(html);
    });
});

运行这段代码,会得到中文乱码。因为人民网(www.people.com.cn)返回的页面编码是GBK的编码。而上述代码是将编码设为了: UTF-8.

当你以为兴高采烈把UTF-8改成GBK就万事大吉的话,那就真的too yang too simple了。不出意外,直接修改编码再重新运行,直接就会得到下面的错误:

string_decoder.js:34
    throw new Error(`Unknown encoding: ${enc}`);
    ^

Error: Unknown encoding: GBK
    at normalizeEncoding (string_decoder.js:34:11)
    at new StringDecoder (string_decoder.js:43:19)
    ....

是的,没错。这压根儿就不认你这个编码格式。

二、寻找原因并解决

经过Object.getPrototypeOf(response)的结果发现。response 原来是IncomingMessage。而IncomingMessage是继承了ReadableStream的,继续向上追溯会找到readable接口。我们知道readable定义了这个setEncoding方法,所以这里response的setEncoding方法其实只支持一部分编码格式:ASCII、UTF-8、UTF-16LE/UCS-2、Base64、Binary、Hex。很遗憾,这里并没有我们期望的GBK什么的...。

那么能不能我们自己来将Buffer转换为对应格式呢?当然是可以的。而且有现成的工具可以完成。

iconv-lite组件可以实现往更多种编码上进行转换。它可以帮我们实现buffer向字符串进行多种编码的转换。支持的编码如下:

utf8, ucs2/utf16-le, ascii, binary, base64, hex,
utf16, utf16-be, utf-7, utf-7-imap, utf32, utf32-le, utf32-be...等等

查看更多支持的编码详情,请点击这里

现在,我们知道了node默认不支持GBK了。只需要得到原来的buffer数据,进行自己转换就好了。

let http  = require("http");
let iconv = require("iconv-lite");

http.get("http://www.people.com.cn",response => {

    // 因为现在自己解码,所以就不设置编码了。
    // response.setEncoding("GBK");

    // buffer数据现在使用数组来保存
    let buffer = [];
    let bufferLength = 0;

    response.on("data", chunk => {
        buffer.push(chunk);
        bufferLength += chunk.length;
    });

    response.on("end", () => {

        // 现在将所有buffer组合为一个整体buffer
        let bufferData = Buffer.concat(buffer, bufferLength);

        // 使用 iconv 以 GBK 编码转换为字符串。
        var html = iconv.decode(bufferData, "GBK");

        console.log(html); // 现在得到的页面内容就没有乱码的了。
    });
});
Full text complete, Reproduction please indicate the source. Help you? Not as good as one:
Comment(Comments need to be logged in. You are not logged in.)
You need to log in before you can comment.

Comments (0 Comments)