简介
Base64 是一种将任意二进制数据转换为可打印 ASCII 字符的编码方式。它本质上是 二进制 → 文本 的编码方案,常用于网络传输或文本协议中嵌入二进制数据。
一个常见的误区是将 Base64 看作为加密算法,实际上 Base64 只是一种编码方式,不具备加密功能。
Base64 使用 6 bit 表示一个字符,因此有 2^6 = 64 个不同字符,编码表包含:
- 26 个大写字母
- 26 个小写字母
- 10 个数字
- 2 个符号:
+和/ =用于填充
下面是标准 Base64 编码表:
| Value | Encoding | Value | Encoding | Value | Encoding | Value | Encoding |
|---|---|---|---|---|---|---|---|
| 0 | A | 16 | Q | 32 | g | 48 | w |
| 1 | B | 17 | R | 33 | h | 49 | x |
| 2 | C | 18 | S | 34 | i | 50 | y |
| 3 | D | 19 | T | 35 | j | 51 | z |
| 4 | E | 20 | U | 36 | k | 52 | 0 |
| 5 | F | 21 | V | 37 | l | 53 | 1 |
| 6 | G | 22 | W | 38 | m | 54 | 2 |
| 7 | H | 23 | X | 39 | n | 55 | 3 |
| 8 | I | 24 | Y | 40 | o | 56 | 4 |
| 9 | J | 25 | Z | 41 | p | 57 | 5 |
| 10 | K | 26 | a | 42 | q | 58 | 6 |
| 11 | L | 27 | b | 43 | r | 59 | 7 |
| 12 | M | 28 | c | 44 | s | 60 | 8 |
| 13 | N | 29 | d | 45 | t | 61 | 9 |
| 14 | O | 30 | e | 46 | u | 62 | + |
| 15 | P | 31 | f | 47 | v | 63 | / |
编码步骤
当对字符串进行 Base64 时,必须先根据某种字符集(通常是 UTF-8)将字符串编码为字节数据,然后再进行 Base64 转换。
如果字符串仅包含 ASCII 字符,此时所有字符编码均为单字节,计算过程简单。
下面以字符串 Mari 为例,演示 ASCII 情况的 Base64 编码步骤。
1 | Array.from( "Mari" ) |
在得到二进制数据后,Base64 将其按照 6 位一组进行分割,分割后不足 6 位在后面补零。
根据上面得到的结果,分割后得到:
1 | 010011 010110 000101 110010 011010 010000 |
然后将每一位根据 Base64 编码表进行转换,得到:
1 | TWFyaQ |
Base64 编码后的字符串长度需要为 4 的倍数,如果不足则需要使用 = 补充,因此对上方的结果作最后补充处理,得到:
1 | TWFyaQ== |
这就是 Base64 的编码步骤,依次方式反向操作也可以将 Base64 编码的字符串解码为原始数据。
JavaScript 中的操作方法
JavaScript 提供了 btoa 与 atob 用于 Base64 编解码:
1 | btoa( "Mari" ) // "TWFyaQ==" |
需要注意:btoa 只能处理 Latin1(ISO-8859-1)字符,即 单字节范围 0–255。
对于 UTF-8 字符(如中文、emoji),由于实际编码需要多字节,直接调用 btoa 会抛出异常。
1 | "M".codePointAt( 0 ).toString( 2 ) // "1001101" 单字节字符 |
因此在现代 JavaScript 中,处理非 ASCII 字符(UTF-8)时,需要先将字符串转换为 UTF-8 字节,此时存在两种常见方式:
使用 TextEncoder / TextDecoder(推荐)
这种方式最规范,可以配合文件、网络流等使用。生成的 Base64 与其他语言完全兼容,即接收到后直接解码即可,无须额外处理。
1 | function base64Encode( str ) { |
encodeURIComponent 方案
这个方案有几个缺陷:
- 无法处理二进制数据,只适用于文本字符串
- 其他语言/环境接收到 Base64 编码后无法直接解码为原始字符串,需要多进行一步 URL decode
- 性能较差
其本质是分几个步骤:
- 先将字符串用
encodeURIComponent转为百分号编码字符串 - 再将百分号编码字符串传入
btoa进行 Base64 编码 - 解码时反向操作,即先用
atob解码 Base64,再用decodeURIComponent转回原始字符串
此时他是对“百分号文本”编码,而不是对“原始字符串”编码,这是非常不标准也不方便使用的
1 | function base64Encode( str ) { |