Base64
Base64 是一组相似的二进制到文本编码方案,通过将二进制数据转换为基数 64 表示,将其表示为 ASCII 字符串格式。术语 Base64 源于特定的 MIME 内容传输编码。
Base64 编码方案通常用于对二进制数据进行编码,以便在只能处理 ASCII 文本(或某种不能接受任意二进制数据的 ASCII 超集)的介质上存储或传输。这确保了数据在传输过程中保持完整无修改。Base64 的常见应用包括:
Base64 字符
当单独使用“Base64”一词指代特定算法时,通常指 RFC 4648 第 4 节中概述的 Base64 版本,该版本使用以下字母表表示基数 64 位,并使用 = 作为填充字符:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
URL 和文件名安全的 Base64
此定义的一个常见变体仅允许在文件名和 URL 值中安全使用的字符。这个版本在 RFC 4648 第 5 节中定义,省略了填充,并将 + 和 / 替换为 - 和 _。
如果您不将数据放入路径段或查询参数中,则不需要此编码——例如,数据 URL 没有这两者,可以使用标准 Base64 编码。
编码后大小增加
每个 Base64 数字代表 6 位数据(64 = 26)。因此,输入字符串/二进制文件的三个 8 位字节(3×8 位 = 24 位)可以用四个 6 位 Base64 数字(4×6 = 24 位)表示。
这意味着字符串或文件的 Base64 版本通常比其源文件大大约三分之一(确切的大小增加取决于各种因素,例如字符串的绝对长度、其长度除以 3 的余数以及是否使用填充字符)。
最后一个块
Base64 字符串可以分成 4 个字符的块,最后一个块的字符数可能少于 4 个。最后一个块可以用 = 字符填充,使其恰好为 4 个字符长。排除填充字符,最后一个块可以是以下之一:
- 2 个字符:编码 12 位,表示 1 字节(8 位)数据
- 3 个字符:编码 18 位,表示 2 字节(16 位)数据
- 4 个字符:编码 24 位,表示 3 字节(24 位)数据
在前两种情况下,字符可能包含 4 或 2 个额外的尾随位,这些位不表示任何数据。在这种情况下,RFC 4648 要求编码器将这些位设置为零,解码器如果这些位不为零则可选地抛出错误。例如,如果编码数据是一个字节 0b01010101,那么它需要两个字符 0b010101 (V) 和 0b010000 (Q),其中第二个字符有 4 个尾随位设置为零。解码 VR==(其中第二个字符表示 0b010001)在技术上会得到相同的字节 0b01010101,但解码器可能会因为尾随位不为零而抛出错误。
JavaScript 支持
Uint8Array 类提供了 Uint8Array.fromBase64()、Uint8Array.prototype.toBase64() 和 Uint8Array.prototype.setFromBase64() 方法,用于 Base64 字符串的相互转换。
浏览器还原生提供了两个 JavaScript 函数用于解码和编码 Base64 字符串:
Window.btoa()(也可在 workers 中使用):从二进制数据字符串创建 Base64 编码的 ASCII 字符串(“btoa”应读作“binary to ASCII”)。Window.atob()(也可在 workers 中使用):解码 Base64 编码的字符串(“atob”应读作“ASCII to binary”)。
注意:Base64 是一种二进制编码,而不是文本编码,但 btoa 和 atob 在网络平台支持二进制数据类型之前就被添加。因此,这两个函数使用字符串来表示二进制数据,每个字符的码点代表每个字节的值。这导致了一个常见的误解,即 btoa 可以用于编码任意文本数据——例如,创建一个文本或 HTML 文档的 Base64 data: URL。
然而,字节到码点的对应关系仅对码点小于等于 0x7f 的情况可靠。此外,码点超过 0xff 会导致 btoa 抛出错误,因为超出了 1 字节的最大值。下一节详细介绍了在编码任意 Unicode 文本时如何解决此限制。
参见
- JavaScript API
- 数据 URL
- 维基百科上的 Base64
- RFC 4648 中描述的 Base64 算法