首页  >  文章  >  web前端  >  如何使用“atob”在 JavaScript 中解码 UTF-8 base64 字符串,同时避免编码错误?

如何使用“atob”在 JavaScript 中解码 UTF-8 base64 字符串,同时避免编码错误?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-10-31 21:08:291000浏览

How do you decode UTF-8 base64 strings in JavaScript using `atob` while avoiding encoding errors?

使用 atob 从常见文本源解码 base64

使用 atob 解码来自以 UTF-8 生成输出的服务的 API 响应字符串时,您可能会遇到错误或损坏的字符串编码。这是由于 JavaScript 的 base64 处理的限制:

<code class="js">const notOK = "✓"
console.log(btoa(notOK)); // error</code>

Unicode 问题

即使在 ECMAScript 中解决了此错误,“Unicode 问题”仍然存在,因为 base64 是二进制文件假设每个编码字符占用一个字节的格式。许多 Unicode 字符需要多个字节进行编码,这可能会导致编码失败。

来源:MDN (2021)

<code class="js">const ok = "a";
console.log(ok.codePointAt(0).toString(16)); // 0x61: occupies 1 byte

const notOK = "✓";
console.log(notOK.codePointAt(0).toString(16)); // 0x2713: occupies 2 bytes</code>

二进制互操作性的解决方案

如果您不确定选择哪种解决方案,这可能就是您想要的。继续滚动查看 ASCII base64 解决方案以及此答案的历史记录。

考虑使用二进制方法,将 UTF-8 字符串转换为二进制表示形式,反之亦然。

编码UTF-8 ⇢ 二进制

<code class="js">function toBinary(string) {
  const codeUnits = new Uint16Array(string.length);
  for (let i = 0; i < codeUnits.length; i++) {
    codeUnits[i] = string.charCodeAt(i);
  }
  return btoa(String.fromCharCode(...new Uint8Array(codeUnits.buffer)));
}
encoded = toBinary("✓ à la mode") // "EycgAOAAIABsAGEAIABtAG8AZABlAA=="</code>

解码二进制 ⇢ UTF-8

<code class="js">function fromBinary(encoded) {
  const binary = atob(encoded);
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < bytes.length; i++) {
    bytes[i] = binary.charCodeAt(i);
  }
  return String.fromCharCode(...new Uint16Array(bytes.buffer));
}
decoded = fromBinary(encoded) // "✓ à la mode"</code>

具有 ASCII base64 互操作性的解决方案

要保留 UTF-8 功能,另一种方法是通过建议使用 ASCII base64 互操作性,这可以纠正“Unicode 问题”,同时保持与基于文本的 base64 字符串的兼容性。

编码 UTF-8 ⇢ ASCII base64

<code class="js">function b64EncodeUnicode(str) {
    // Percent-encode Unicode, then convert to byte array
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
        function(match, p1) {
            return String.fromCharCode('0x' + p1);
    }));
}
b64EncodeUnicode('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="</code>

解码 ASCII base64 ⇢ UTF -8

<code class="js">function b64DecodeUnicode(str) {
    // Convert byte array to percent-encoding, then decode
    return decodeURIComponent(atob(str).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}
b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"</code>

TypeScript 支持

<code class="ts">function b64EncodeUnicode(str) {
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
        return String.fromCharCode(parseInt(p1, 16))
    }))
}
function b64DecodeUnicode(str) {
    return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
    }).join(''))
}</code>

附加说明

  • 从 GitHub API 等来源解码 base64 字符串可能需要删除空格Safari。
  • js-base64 和 base64-js 等库也提供了可靠的解决方案。

以上是如何使用“atob”在 JavaScript 中解码 UTF-8 base64 字符串,同时避免编码错误?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn