Base64

Base64 是一组相似的二进制到文本编码方案,通过将二进制数据转换为基数 64 表示,将其表示为 ASCII 字符串格式。术语 Base64 源于特定的 MIME 内容传输编码

Base64 编码方案通常用于对二进制数据进行编码,以便在只能处理 ASCII 文本(或某种不能接受任意二进制数据的 ASCII 超集)的介质上存储或传输。这确保了数据在传输过程中保持完整无修改。Base64 的常见应用包括:

  • 通过 MIME 发送电子邮件
  • XML 中存储复杂数据
  • 对二进制数据进行编码,以便将其包含在 data: URL

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 字符串:

注意:Base64 是一种二进制编码,而不是文本编码,但 btoaatob 在网络平台支持二进制数据类型之前就被添加。因此,这两个函数使用字符串来表示二进制数据,每个字符的码点代表每个字节的值。这导致了一个常见的误解,即 btoa 可以用于编码任意文本数据——例如,创建一个文本或 HTML 文档的 Base64 data: URL。

然而,字节到码点的对应关系仅对码点小于等于 0x7f 的情况可靠。此外,码点超过 0xff 会导致 btoa 抛出错误,因为超出了 1 字节的最大值。下一节详细介绍了在编码任意 Unicode 文本时如何解决此限制。

参见