接口里那串 aGVsbG8= 是什么?为什么图片变成 Base64 后大了一圈?为什么中文解码出来是乱码?这篇文章把 Base64 讲清楚,顺便纠正一个最常见的误解——Base64 不是加密。
Base64 是一种用 64 个可打印字符来表示二进制数据的编码方式。这 64 个字符是:
A-Z (26) a-z (26) 0-9 (10) + / → 合计 64 个
末尾的 = 是填充符
它的核心动作只有一个:把每 3 个字节(24 位)切成 4 组 6 位,每组对应上面表里的一个字符。所以 3 字节的数据编码后变成 4 个字符。
因为很多协议是“纯文本协议”,只保证能安全传输可打印字符。原始二进制字节里可能有换行符、控制字符、null 字节,这些东西在传输途中会被误当作协议指令,或者干脆被截断。
典型场景:
| 场景 | 为什么用 Base64 |
|---|---|
| JSON 里塞二进制 | JSON 是文本格式,不能直接放原始字节 |
| HTTP Basic 认证 | 头信息必须是可打印字符 |
| 邮件附件 | SMTP 是纯文本协议 |
| 图片内联进 HTML/CSS | 避免额外请求,见 data:image/png;base64,... |
| JWT 令牌 | 头部和载荷部分就是 Base64URL 编码的 JSON |
这是纯数学的结果:3 个字节(24 位)的信息,需要用 4 个字符(每个 6 位)来装。
原始数据 3 字节
Base64 后 4 字节
增加比例 4/3 - 1 = 33.3%
所以一个 300 KB 的图片转成 Base64 会变成 400 KB 左右。如果后面还要塞进 JSON 字符串(多一层转义),可能再涨一点。
根源在于:Base64 编码的是字节,不是字符。
而“字符”变成“字节”这一步,依赖字符集。同一个汉字在不同字符集下字节完全不同:
"中"
UTF-8 → E4 B8 AD → Base64: 5Lit
GBK → D6 D0 → Base64: 1tA=
所以编码和解码两边必须约定同一套字符集。现代系统的正确做法是:
乱码的典型原因就是一边用 UTF-8、另一边用 GBK,或者某一步用了系统默认编码(Windows 上常是 GBK)。
标准 Base64 用了 + 和 / 两个字符,而这两个在 URL 里有特殊含义(+ 会被解析成空格,/ 是路径分隔符)。所以有了 URL 安全版 Base64URL:
| 标准 Base64 | Base64URL |
|---|---|
+ | - |
/ | _ |
= 填充 | 常省略 |
JWT 用的就是 Base64URL。如果你把 JWT 丢进 URL 参数后解码失败,先检查是不是把 -、_ 换回了 +、/。
这是最需要纠正的误解。Base64 只是编码,没有密钥,任何人都能解开。
把密码、token 做 Base64 然后放前端,等于把明文贴在页面上——因为 btoa() 是浏览器自带函数,一秒钟就能还原。
+ / = 的处理纯浏览器本地处理,输入的内容不会离开你的电脑。
= 补齐。1 个等号表示补了 1 字节,2 个等号表示补了 2 字节。解码时收到等号是正常现象,不是数据损坏。+ / 是否被换成了 - _(或者反过来)。这三点覆盖九成失败情况。