Base64
Base64 是一组类似的 二进制到文本编码 方案,通过将其转换为基数 64 表示形式,将二进制数据表示为 ASCII 字符串格式。术语 Base64 源自特定的 MIME 内容传输编码。
当单独使用“Base64”一词来指代特定的 算法 时,它通常指的是 RFC 4648 第 4 节中概述的 Base64 版本,该版本使用以下字母表来表示基数 64 数字,以及 =
作为填充字符。
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
一个常见的变体是“Base64 URL 安全”,它省略了填充并用 -_
替换了 +/
,以避免在 URL 路径段或查询参数中可能导致问题的字符。如果您没有将数据放在路径段或查询参数中,则不需要此编码——例如,data URL 既没有路径段也没有查询参数,可以使用标准 Base64 编码。
Base64 编码方案通常用于对二进制数据进行编码,以便存储或通过只能处理 ASCII 文本(或仍然无法接受任意二进制数据的 ASCII 的某个超集)的媒体进行传输。这确保了数据在传输过程中保持完整且不会被修改。Base64 的常见应用包括:
编码大小增加
每个 Base64 数字代表 6 位数据。因此,输入字符串/二进制文件中的三个 8 位字节(3×8 位 = 24 位)可以用四个 6 位 Base64 数字(4×6 = 24 位)表示。
这意味着字符串或文件的 Base64 版本通常比其源文件大大约三分之一(确切的尺寸增加取决于各种因素,例如字符串的绝对长度、其长度模 3 以及是否使用了填充字符)。
JavaScript 支持
浏览器本身提供了两个 JavaScript 函数用于解码和编码 Base64 字符串。
Window.btoa()
(也在 工作线程中可用):从二进制数据字符串创建 Base64 编码的 ASCII 字符串(“btoa”应理解为“二进制到 ASCII”)。Window.atob()
(也在 工作线程中可用):解码 Base64 编码的字符串(“atob”应理解为“ASCII 到二进制”)。
注意:Base64 是一种二进制编码,而不是文本编码,但 btoa
和 atob
是在 Web 平台支持二进制数据类型之前添加的。因此,这两个函数使用字符串来表示二进制数据,每个字符的 代码点 表示每个字节的值。这导致了一个普遍的误解,即 btoa
可用于编码任意文本数据——例如,创建文本或 HTML 文档的 Base64 data:
URL。
但是,字节到代码点的对应关系仅对代码点高达 0x7f
时才可靠地成立。此外,超过 0xff
的代码点会导致 btoa
抛出错误,因为超过了 1 个字节的最大值。下一节详细介绍了在编码任意 Unicode 文本时如何解决此限制。
“Unicode 问题”
由于 btoa
将其输入字符串的代码点解释为字节值,因此如果字符的代码点超过 0xff
,则在字符串上调用 btoa
将导致“字符超出范围”异常。对于需要编码任意 Unicode 文本的用例,需要先将字符串转换为其在 UTF-8 中的组成字节,然后对这些字节进行编码。
最简单的解决方案是使用 TextEncoder
和 TextDecoder
在 UTF-8 和字符串的单字节表示之间进行转换。
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 Ā 𐀀 文 🦄"
转换任意二进制数据
上一节中的 bytesToBase64
和 base64ToBytes
函数可直接用于在 Base64 字符串和 Uint8Array
之间进行转换。
为了获得更好的性能,可以通过 Web 平台本身的 FileReader
和 fetch
API 本地异步地在 base64 数据 URL 之间进行转换。
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]
另请参阅
- JavaScript API
Window.atob()
(也在 工作线程中可用)Window.btoa()
(也在 工作线程中可用)
- 数据 URL
- Base64 在维基百科上
- 在 RFC 4648 中描述的 Base64 算法