实习生问我:"为什么这个 CSS 里图片是一长串字符,不是图片链接?" 他指的是 background: url(data:image/png;base64,iVBORw0KG...) 这种。 又问:"这是不是加密了?"
这是 Base64,而且它不是加密。Base64 是前端 / 后端开发天天见但很多人没真正理解的东西。 这篇讲清楚:Base64 是什么、为什么图片要转 Base64、什么时候该用什么时候是坑。
Base64 是什么:把二进制变成纯文本
计算机里的数据分两种:文本(你能读的字符)和二进制(图片 / 视频 / 文件的字节)。
问题来了:有些场景只能传文本,不能传二进制 —— 比如 URL、JSON 字段、邮件正文、CSS 文件。 你不能直接把图片的二进制塞进 JSON 字符串里(会破坏 JSON 结构)。
Base64 就是解决这个问题的:它把任意二进制数据,转换成只用 64 个安全字符 (A-Z、a-z、0-9、+、/)表示的纯文本。这样二进制就能"伪装"成文本, 在只能传文本的地方畅通无阻。
最重要的一点:Base64 不是加密
这是最常见的误区,一定要纠正。
Base64 是编码(encoding),不是加密(encryption)。区别:
- 编码:换一种表示形式,任何人都能一键还原。无保密性
- 加密:用密钥锁住,没密钥无法还原。有保密性
任何人拿到 Base64 字符串,粘到解码工具里立刻还原成原文。 所以绝对不能拿 Base64 当加密用 —— 把密码 Base64 编码后存数据库, 等于明文存储。要保密必须用 AES 等真正的加密算法。
为什么图片要转 Base64 嵌网页
正常情况下,网页里的图片是这样引用的:img src="logo.png", 浏览器会单独发一个 HTTP 请求去服务器下载这个图片。
但如果把图片转成 Base64 直接写进 HTML / CSS(Data URL), 浏览器不需要额外发请求,直接解码显示。好处:
- 减少 HTTP 请求:小图标内嵌,省去一次次的网络往返
- 单文件携带:HTML 自带图片,不依赖外部文件
- 避免图片丢失:不会出现"图片裂了"的情况
但 Base64 内嵌图片有代价
不是所有图片都适合转 Base64。代价有两个:
代价 1:体积膨胀 33%
Base64 把每 3 字节编码成 4 字符,体积增加约 33%。 原本 100KB 的图片转 Base64 变成约 133KB。
代价 2:不能被浏览器缓存
正常的图片文件,浏览器会缓存,第二次访问直接用缓存。 但内嵌的 Base64 图片是 HTML / CSS 的一部分,每次加载页面都要重新传输, 无法单独缓存。
什么时候该用,什么时候是坑
适合用 Base64 内嵌
- 小图标 / 小 logo(5KB 以下):减少请求,体积膨胀可忽略
- 邮件内嵌图片:邮件正文带图,不依赖外部链接
- 一次性的小图:只用一次,不需要缓存
- CSS 里的小背景图 / 渐变纹理
不该用 Base64(是坑)
- 大图片:体积膨胀 33% + 不能缓存,加载更慢
- 多页面复用的图片:每个页面都重复嵌入,浪费流量
- 需要保密的数据:Base64 没有保密性,等于明文
Data URL 的结构
你看到的 data:image/png;base64,iVBORw0KG... 拆解:
data:—— 协议头,告诉浏览器这是内嵌数据image/png—— 媒体类型,说明这是 PNG 图片;base64—— 标识后面是 Base64 编码,iVBORw0KG...—— 实际的 Base64 数据
Base64 的字符:+ / = 是什么
- A-Z a-z 0-9:前 62 个字符
- + 和 /:第 63、64 个字符
- =:末尾填充符,原始数据不是 3 的倍数时补齐
还有一种 URL-safe Base64:因为 + 和 / 在 URL 里有特殊含义, 所以 URL 场景把 + 换成 -、/ 换成 _。 JWT 用的就是这种变体。
中文转 Base64 的正确姿势
中文转 Base64 必须先用 UTF-8 编码:
中文 → UTF-8 字节 → Base64(编码)
Base64 → 字节 → UTF-8 → 中文(解码)
如果出现乱码,99% 是编码环节没用 UTF-8(用了 GBK)。 前端用 TextEncoder / TextDecoder 处理 UTF-8 最稳。
总结
Base64 是把二进制变成纯文本的编码方式,不是加密。 小图标内嵌网页能减少请求,但大图片用 Base64 是坑(体积膨胀 + 不能缓存)。 记住:Base64 没有任何保密性,千万别拿它当加密。
站里的Base64 编解码工具 支持文字 / 文件 Base64 互转 + 图片转 Data URL,纯浏览器本地处理。 如果你在解 JWT 里的 Base64 段,用JWT 解析工具更直接。