Window: btoa() 方法

Baseline 已广泛支持

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

Window 接口的 btoa() 方法从一个二进制字符串(即,字符串中的每个字符都被视为二进制数据的一个字节)创建一个 Base64 编码的 ASCII 字符串。

你可以使用此方法编码可能导致通信问题的数据,传输数据,然后使用 Window.atob() 方法再次解码数据。例如,你可以编码控制字符,例如 ASCII 值 0 到 31。

如果你的数据在一个 Uint8Array 对象中,也请考虑使用 Uint8Array.prototype.toBase64() 方法,以避免创建包含原始字节的字符串。

语法

js
btoa(stringToEncode)

参数

stringToEncode

要编码的二进制字符串。JavaScript 中的字符串编码为 UTF-16,因此这意味着每个字符的代码点必须小于 256,表示一个字节的数据。

返回值

一个包含 stringToEncode 的 Base64 表示的 ASCII 字符串。

异常

InvalidCharacterError DOMException

字符串中包含的字符不适合单个字节。有关更多详细信息,请参阅下面的“Unicode 字符串”。

示例

js
const encodedData = window.btoa("Hello, world"); // encode a string
const decodedData = window.atob(encodedData); // decode the string

Unicode 字符串

Base64,顾名思义,需要二进制数据作为输入。就 JavaScript 字符串而言,这意味着字符串中每个字符的代码点只占用一个字节。因此,如果你将一个包含占用多个字节的字符的字符串传递给 btoa(),你将收到一个错误,因为这不被视为二进制数据。

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

const notOK = "✓";
console.log(notOK.codePointAt(0).toString(16)); // 2713: occupies > 1 byte

console.log(window.btoa(ok)); // YQ==
console.log(window.btoa(notOK)); // error

由于 btoa 将其输入字符串的代码点解释为字节值,因此如果字符的代码点超过 0xff,在字符串上调用 btoa 将导致“字符超出范围”异常。对于需要编码任意 Unicode 文本的用例,需要先将字符串转换为其组成字节的 UTF-8,然后编码这些字节。

最简单的解决方案是使用 TextEncoderTextDecoder 在 UTF-8 和字符串的单字节表示之间进行转换。

js
function base64ToBytes(base64) {
  const binString = atob(base64);
  return Uint8Array.from(binString, (m) => m.codePointAt(0));
}

function bytesToBase64(bytes) {
  const binString = Array.from(bytes, (byte) =>
    String.fromCodePoint(byte),
  ).join("");
  return btoa(binString);
}

// Usage
bytesToBase64(new TextEncoder().encode("a Ā 𐀀 文 🦄")); // "YSDEgCDwkICAIOaWhyDwn6aE"
new TextDecoder().decode(base64ToBytes("YSDEgCDwkICAIOaWhyDwn6aE")); // "a Ā 𐀀 文 🦄"

转换任意二进制数据

上一节中的 bytesToBase64base64ToBytes 函数可以直接用于在 Base64 字符串和 Uint8Array 之间进行转换。

为了获得更好的性能,通过 FileReaderfetch API,可以在 Web 平台中本地实现 Base64 数据 URL 之间的异步转换。

js
async function bytesToBase64DataUrl(bytes, type = "application/octet-stream") {
  return await new Promise((resolve, reject) => {
    const reader = Object.assign(new FileReader(), {
      onload: () => resolve(reader.result),
      onerror: () => reject(reader.error),
    });
    reader.readAsDataURL(new File([bytes], "", { type }));
  });
}

async function dataUrlToBytes(dataUrl) {
  const res = await fetch(dataUrl);
  return new Uint8Array(await res.arrayBuffer());
}

// Usage
await bytesToBase64DataUrl(new Uint8Array([0, 1, 2])); // "data:application/octet-stream;base64,AAEC"
await dataUrlToBytes("data:application/octet-stream;base64,AAEC"); // Uint8Array [0, 1, 2]

注意:对于支持环境,也请考虑原生的 Uint8Array.fromBase64()Uint8Array.prototype.toBase64()Uint8Array.prototype.setFromBase64() 方法。

规范

规范
HTML
# dom-btoa-dev

浏览器兼容性

另见