utf-8编码的字符串到缓冲区node.js

Roh*_*ara 2 base64 encoding node.js axios

在 NodeJS Express 服务器 #1 上,我在 HTTP 响应中从另一个 NodeJS 服务器 #2 接收二进制流数据。我想将此数据编码为 Base64。我在编码方面遇到问题。我是这样做的,如下所示。

let result = await axios.post(firmwareDownloadURL, {
        id: 'firmware1'
      }, {
        headers: {
          'Content-Type': 'application/json',
        }
      });
let buff1 = new Buffer.from(result.data);
let base64Firmware1 = buff1.toString('base64');
Run Code Online (Sandbox Code Playgroud)

的值buff1不正确,因此base64Firmware1也是错误的。我通过使用 fs 从我的系统读取固件文件来进行比较。

let buff2 = fs.readFileSync('./f1.bin');
let base64Firmware2 = buff3.toString('base64');
Run Code Online (Sandbox Code Playgroud)

和不匹配buff1buff2

buff <Buffer ef bf bd ef bf bd ef bf bd 00 01 ef bf bd 48 ef bf bd ef bf bd 01 6d 02 08 22 ef bf bd ef bf bd 0a ef bf bd ef bf bd 6e 6d 02 08 ef bf bd 0a ef bf bd ... 612 more bytes>

buff2 <Buffer a7 a3 fe 00 01 8d 48 a7 a6 01 6d 02 08 22 a7 a3 0a a7 a6 6e 6d 02 08 f1 a7 a3 0a a7 a6 f7 6d 02 08 b4 a7 a3 32 a7 a6 14 6e 02 08 39 a7 a3 06 a7 a6 56 ... 307 more bytes>
Run Code Online (Sandbox Code Playgroud)

有趣的是,当我转换buff2为字符串并与result.data它们匹配进行比较时。

if (buff2.toString() === result.data && buff2.toString().length ==  result.data.length) {
  console.log('equal');
}
Run Code Online (Sandbox Code Playgroud)

它在控制台上打印相等。请帮我确定,我错过了什么?

cub*_*brr 7

您对字符串化时数据匹配的观察结果是正确的,因为这正是 Axios 在幕后所做的事情。问题是 Axios 默认情况下会将响应数据字符串化。在 Node.js 上,这意味着它会调用 Buffer.toString('utf8')生成您所看到的内容。因此,字节被解释为 UTF-8,这会将无效的代码单元转换为U+FFFD REPLACEMENT CHARACTERUnicode 代码点,如以下文档Buffer.toString()中所指定:

如果encoding'utf8'并且输入中的字节序列不是有效的 UTF-8,则每个无效字节将替换为替换字符U+FFFD

代码U+FFFD点以 UTF-8 编码为代码单元EF BF BD,您可以在数据中看到。

事后将已字符串化的缓冲区转换为原始缓冲区是不可能的,因为所有非 UTF8 代码单元都将转换为U+FFFD,这会丢失信息。要解决编码问题,您可以使用responseTypeAxios 中的选项来指定您需要原始缓冲区:

let res = await axios.post(
  firmwareDownloadURL,
  {
    id: "firmware1",
  },
  {
    headers: {
      "Content-Type": "application/json",
    },
    responseType: "arraybuffer",
  }
);
let buff1 = res.data;
let base64Firmware1 = buff1.toString("base64");
Run Code Online (Sandbox Code Playgroud)

有效选项responseType'arraybuffer''document''json''text''stream',在浏览器环境中使用 Axios 时为'blob'


附带说明一下,如果您有兴趣了解有关 Unicode“代码点”到底是什么的更多信息,我建议您阅读本文