Base64 编码原理详解:为什么体积增大 1/3?中文为何会乱码?
Base64 是什么:不是加密,是编码
Base64 是一种用 64 个可打印字符表示任意二进制数据的编码方案。它不提供任何保密性——任何人拿到编码结果都能解出来,它的目的是把二进制数据变成可以在文本协议(HTTP、JSON、邮件)里安全传输的 ASCII 字符串。常用场景:图片转 Data URI、JWT 的 payload、HTTP Basic 认证、邮件附件。
编码原理:6 比特一组
字符集固定 64 个字符,恰好 2 的 6 次方,所以每个字符能表示 6 个比特。二进制数据按 8 比特(1 字节)为单位,要凑成 6 比特一组,就需要找最小公倍数:
3 字节 = 24 bit = 4 组 × 6 bit
输入 3 字节 → 输出 4 个 Base64 字符
这就是体积比率的来源:4/3 = 1.333,增加 33.3%。比如 3MB 的图片编码后约 4MB。
填充符 = 的作用
数据长度不一定总是 3 的倍数。剩余 1 或 2 字节时,用 = 补足:
输入 1 字节 → 2 字符 + 2 个 =
输入 2 字节 → 3 字符 + 1 个 =
解码端看到 = 就知道丢弃末尾的无效位。所以 Base64 长度公式:ceil(n/3)*4。
为什么中文会乱码?UTF-8 是根源
Base64 只处理“字节”,不关心“字符”。中文在 UTF-8 下是 3 字节/字,如果编码时用了别的字符集(如 GBK 的 2 字节/字)或解码端用了错误的编码还原,就会乱码。正确姿势:
// 编码:UTF-8 → 字节 → Base64
new TextEncoder().encode("你好") // 得到 UTF-8 字节
// 解码:Base64 → UTF-8 字节 → 文本
new TextDecoder("utf-8").decode(bytes)
直接用 Base64 在线编解码工具(内置 UTF-8 安全处理)可避免此坑。
URL Safe 变体:+/= 的兼容问题
标准 Base64 的 +、/、= 在 URL 中有特殊含义,直接放进 Query String 会被转义或截断。解决方案是 URL Safe 变体:+→-,/→_,并去掉末尾 =。JWT 的签名部分用的正是这种变体。
常见问题
Q:Base64 和 Base64URL 有什么区别? 字符表不同:Base64URL 用 - 和 _ 替换 + 和 /,且省略填充 =,用于 URL 和 JWT。
Q:Base64 能代替加密吗? 不能。Base64 是可逆的公开编码,没有任何安全性,敏感数据必须先加密再编码。
Q:为什么邮件里看到的 Base64 很长? 因为 MIME 规范要求每 76 字符插入一个换行,换行在解码时会被忽略,这属于规范内的换行而非错误。
