Base64 是什么?用途、原理和 5 个常见误区
在网页源码里看到一长串 data:image/png;base64,iVBORw0KGgo...,在接口里看到 Authorization: Basic YWRtaW46MTIz,在 JWT 令牌里看到三段用点分开的乱码——这些都是 Base64。它是开发中最常用的编码之一,也是被误用最多的之一。
一、Base64 解决什么问题
很多传输通道最初只为“可打印文本”设计,比如电子邮件、URL、JSON 字符串、HTTP 头。图片、压缩包这些二进制数据里有大量不可打印的字节,直接塞进去可能被截断或改坏。Base64 的作用就是:把任意字节变成只由 64 个安全字符组成的文本,到了目的地再原样还原。
这 64 个字符是:A–Z、a–z、0–9,再加 + 和 /,另外用 = 作为补位。
二、原理:3 个字节变 4 个字符
以英文单词 Man 为例:
- 三个字母的 ASCII 码是 77、97、110,二进制为 01001101 01100001 01101110,共 24 位。
- 按每 6 位切成 4 组:010011、010110、000101、101110,对应十进制 19、22、5、46。
- 查编码表:19→T,22→W,5→F,46→u,结果是
TWFu。
因为 6 位只能表示 64 种值,所以每 3 个字节(24 位)正好变成 4 个字符。这也解释了体积会增加约 1/3:100 KB 的图片转成 Base64 后大约 133 KB。
如果原始数据长度不是 3 的倍数,就在末尾补 =:剩 1 个字节补两个 ==,剩 2 个字节补一个 =。例如 Hello(5 字节)编码为 SGVsbG8=。
三、中文为什么要先转 UTF-8
Base64 处理的是“字节”,不是“文字”。中文必须先按某种字符编码转成字节,才能再做 Base64。同一个“你好”:
- 按 UTF-8 是 6 个字节,Base64 结果为
5L2g5aW9; - 按 GBK 是 4 个字节,结果完全不同。
所以两个工具对中文编码结果不一致时,多半是一个用了 UTF-8、另一个用了 GBK。现在网页和接口的通行做法是统一用 UTF-8。在浏览器里,直接对中文调用 btoa("你好") 会报错,因为 btoa 只接受单字节字符,需要先用 TextEncoder 转成 UTF-8 字节。
四、URL 安全的 Base64
标准 Base64 里的 + 和 / 在网址中有特殊含义,= 也常被当作参数分隔。因此 RFC 4648 定义了“URL 和文件名安全”的变体:把 + 换成 -,/ 换成 _,末尾的 = 通常省略。JWT 令牌的三段就是用这种格式。解码时把字符换回来、补齐 =,就能按标准方式解码。
五、五个常见误区
误区 1:Base64 是加密。不是。它没有密钥,任何人都能还原。把密码 Base64 一下放进配置文件,等于明文存储。HTTP Basic 认证里的 YWRtaW46MTIz 解码就是 admin:123,所以 Basic 认证必须配合 HTTPS 使用。
误区 2:Base64 能压缩数据。恰恰相反,它会让数据变大约 33%。
误区 3:小图片都应该转成 Base64 内嵌。内嵌可以少一次请求,但会让 HTML 或 CSS 变大、无法被浏览器单独缓存。一般只对很小的图标这样做,大图仍用独立文件。
误区 4:解码出乱码就是数据坏了。也可能原始内容本来就是图片、压缩包等二进制数据,或者原文用的不是 UTF-8。先确认数据来源和类型。
误区 5:有换行的 Base64 不能解码。电子邮件等场景会每 76 个字符插入换行,这是规范允许的,解码前去掉空白即可。
六、命令行和代码示例
# Linux / macOS
echo -n "你好" | base64 # 5L2g5aW9
echo "5L2g5aW9" | base64 -d # 你好
# Python
import base64
base64.b64encode("你好".encode("utf-8"))
base64.urlsafe_b64encode(b"??>>") # b'Pz8-Pg=='
注意 echo 要加 -n,否则末尾的换行符也会被编码进去,结果会多出 Cg== 之类的尾巴。
七、在线编解码
本站的 Base64 编解码工具 统一按 UTF-8 处理中文,可以勾选 URL 安全格式;解码时自动识别标准和 URL 安全两种写法、自动补齐 =,遇到非法字符或非文本数据会给出提示。全部在浏览器本地运行,不会上传你粘贴的内容。如果要把一段文字分享到手机上,也可以用 二维码生成器 直接生成二维码。