Base64 是什么:原理、= 号的来历与「图片转 Base64」的正确用法

接口报文里一长串以 = 结尾的乱码、HTML 里 data:image/png;base64, 开头的图片地址,都是 Base64。它常被误解为「加密」,这篇先纠正这个误会,再讲怎么正确用它。

一、Base64 是编码,不是加密

Base64 的作用是把任意二进制数据用 64 个可打印字符表示出来(A–Z、a–z、0–9、+、/)。任何文件——图片、压缩包、中文文本——在它眼里都是字节序列,转完任何人都能原样还原。它没有密钥、不保密,只解决「二进制数据在纯文本环境里怎么安全传输」的问题:邮件协议、JSON 报文、URL 参数、CSS 内嵌,这些场景不允许出现乱码字节,Base64 让二进制「伪装」成普通文本。

二、3 字节变 4 字符:体积变大的数学原因

1 字节 = 8 位,3 字节 = 24 位。24 位刚好拆成 4 个 6 位组,每个 6 位组(0–63)查表对应一个字符。所以 Base64 把每 3 字节编码成 4 字符,体积膨胀 33%。这也是它不适合大文件的原因——一张 3MB 的图编码后约 4MB,还要额外占内存解码。

结尾的 = 是补位符:数据长度不是 3 的倍数时,最后剩 1 字节补 2 个 =,剩 2 字节补 1 个 =。所以 = 最多出现两个,看到它就知道这段编码「尾部有零头」。

三、图片转 Base64:什么时候值得用

场景建议
≤ 2KB 的小图标、loading 动画帧值得内嵌:省一次 HTTP 请求,渲染更快
10KB 以上的正常图片不要内嵌:体积 +33%,且无法被浏览器缓存独立复用
多个页面共用的图不要内嵌:每页都带一份,白白重复传输

正确用法是在 CSS 里写 background-image: url(data:image/png;base64,xxxx),或 HTML 里 <img src="data:image/png;base64,xxxx">。注意 data: 前缀和 MIME 类型(png/jpeg/svg)必须写对,否则图片不显示。

四、手算一个编码例子,彻底理解它

拿经典例子 "Man" 走一遍。三个字母的 ASCII:M=77、a=97、n=110,写成二进制分别是 01001101、01100001、01101110。拼成 24 位串:010011 010110 000101 101110。每组 6 位转十进制:19、22、5、46。查 Base64 表(A=0,B=1……Z=25,a=26……):19=T、22=W、5=F、46=u。所以 "Man" 编码后是 TWFu——和标准库输出一致。

如果原文长度不是 3 的倍数,比如 "Ma" 只有两个字节 16 位,补两个 0 凑成 18 位得 3 个字符,再补一个 = 凑满 4 字符,输出 "TWE="。这个例子能解释你见到的一切 Base64 特征:为什么输出长度总是 4 的倍数、= 为什么只出现在结尾、为什么同样内容每次编码结果都一样(它是确定性映射,与加密的本质区别)。

🔄 Base64 编码:文本与 Base64 双向转换;图片转 Base64:上传图片直接生成 data URI,本地处理不上传。

五、三个排查技巧

  1. 长度判断内容类型:4 的倍数且结尾 0–2 个 = 是标准 Base64;不满足说明字符串被截断或混入了换行——很多邮件客户端每 76 个字符插一个换行,先去掉再解码;
  2. 乱码先查字符集再查编码:解码结果是一串问号或方块,说明字节还原是对的、字符集解释错了。中文场景九成是 GBK 与 UTF-8 混用;
  3. URL 场景先做变体替换:从 URL 参数里拿到的 Base64 解码失败,先把 - 换成 +、_ 换成 /、补上缺少的 = 再试,Base64URL 变体是 JWT、签名参数的默认格式。

常见问题

问:Base64 里的 + 和 / 在 URL 里出问题怎么办?
URL 场景用变体「Base64URL」:+ 换成 -,/ 换成 _,去掉补位 =。JWT 令牌用的就是它。

问:为什么解码后中文变乱码?
Base64 只负责字节级还原,乱码出在字符集环节——编码前必须先按 UTF-8 把文本转字节,解码后也按 UTF-8 还原,两端口径不一致就会出现乱码。