为什么 Base64 会让文件变大 33%?编码开销原理详解
很多教程会说一句"Base64 会让数据变大 33%"然后跳过。但这笔账怎么算,什么时候真的要算,什么时候可以忽略,是写 API、做图片内嵌、估带宽之前应该搞清楚的事。短数据尤其反直觉,2 字节字符串编码后体积翻倍。
这篇用三个具体例子把账算清楚。想在自己的数据上验证一下开销?粘到我们的 Base64 编解码工具 里对比一下长度。
为什么是 33%
Base64 用 64 个可打印字符表示任意字节序列。64 个符号需要 6 个 bit 表示(2^6 = 64)。原始字节是 8 bit。所以每 6 bit 原始数据需要 1 个 Base64 字符承载。
为了让数据按整数对齐,Base64 规定每 3 个原始字节(24 bit)编码成 4 个 Base64 字符(4 × 6 = 24)。3 字节变 4 字节,多出来的就是开销:
3 字节 × 8 bit = 24 bit
↓ 重新打包成 4 组 6 bit
4 字符 × 6 bit = 24 bit
体积变化: 3 → 4,膨胀 (4-3)/3 = 33.33%
这个比例是固定的。无论你编码什么,Base64 输出的字符数都等于原始字节数的 4/3 倍(向上取整到 4 的倍数)。
三个具体例子
例 1: "Hi"(2 字节,膨胀 100%)
原始: H(72) i(105)
二进制: 01001000 01101001
补 0: 01001000 01101001 00000000
6-bit: 010010 000110 100100 (第三段只有 2 个有效 bit)
查表: S G k (第四字符位置用 = 填)
结果: SGk= (4 字符)
2 字节 → 4 字符,膨胀 100%。短数据 Base64 化非常亏。
例 2: "Hello"(5 字节,膨胀 60%)
原始: H e l l o
字节: 72 101 108 108 111
3 字节分组: (H e l) + (l o ?)
编码: SGVs bG8=
结果: SGVsbG8= (8 字符)
5 字节 → 8 字符,膨胀 60%。
例 3: 1 MB 文件(膨胀 33.4%)
1 MB = 1048576 字节。
Base64 字符数 = ceil(1048576 / 3) × 4
= 349526 × 4
= 1398104 字符
≈ 1.333 MB
这就是教科书说的"33%"。文件越大,越接近理论值。
一般公式
对于 n 字节的原始数据:
Base64 字符数 = 4 × ceil(n / 3)
= 填充的数量取决于 n mod 3:
| n mod 3 | 填充 = 数量 | 编码后长度 | 实际开销 |
|---|---|---|---|
| 0 | 0 | 4n/3 | 33.3% |
| 1 | 2 | 4(n+2)/3 | 33% - 300% |
| 2 | 1 | 4(n+1)/3 | 33% - 100% |
最后一列的范围表示,当 n 很小(1-2 字节)时开销占比远超 33%。这就是为什么 "Hi" 膨胀 100%。
什么时候这 33% 真的算事
邮件附件
SMTP 历史上只接受 ASCII 文本,二进制附件必须 Base64 编码。10 MB 附件实际占用 13.3 MB 网络流量。Gmail、Outlook 现在仍走这条路。
Data URI 内嵌
把小图片或字体直接嵌进 HTML/CSS,减少 HTTP 请求:
<img src="data:image/png;base64,iVBORw0KGgoAAAANS..." />
代价是 HTML 体积涨 33%。10 KB 图标变成 13.3 KB 内嵌字符串。几十个小图标累积起来明显。
JWT
JWT 的 header、payload、signature 三段都是 Base64URL 编码。token 越长,HTTP header 越大,影响每个请求的延迟。
API 响应里的二进制字段
如果 API 返回图片、音频或加密数据,Base64 编码后响应体积涨 33%,移动端流量敏感场景要权衡。
什么时候可以忽略
小数据
几十字节的 token、ID、签名,编码后多几十字节,几乎看不见。
已经压缩过的数据
Base64 编码后再做 gzip,通常能压回接近原始大小。HTTP 开启 gzip 的服务端几乎不用为 Base64 付净增成本。
调试场景
调试用的 hash、token 显示,体积完全无所谓。
Base64URL:去掉 URL 麻烦
标准 Base64 包含 +、/、=,这些字符在 URL 里要么非法要么需要转义。Base64URL 是变体:
| 标准 Base64 | Base64URL |
|---|---|
+ | - |
/ | _ |
=(填充) | 通常去掉 |
JWT 强制要求 Base64URL。体积上和标准 Base64 一样还是 33% 开销,只是字符替换。
在本地算这笔账
要预估 Base64 后的大小、验证 Base64 字段、把图片转 Data URI,这些操作不该把原始数据贴到不信任的网站。Token、密钥、用户数据都可能藏着。
Base64 编解码工具 编码后会给出体积统计行:输入字节 → 输出字符、膨胀百分比,以及填充 = 个数(URL-safe 模式去掉填充,膨胀会略低)。测旧数据时切换字符集到 GBK 或 Latin-1——开销按字符集编码后的字节数算,不是 JavaScript 字符串的 .length。图片转 Base64 显示图片编码后的体积变化,Data URI 生成器 直接生成可粘贴到 HTML 的内嵌字符串。全部在浏览器本地处理,数据不离开你的设备。
若要在同一载荷上对比 Base32 / Base58 / Base64,用 Base32/Base58 编码器 的并排面板。
记住公式:4 × ceil(n/3)。下次估 API 响应大小、判断要不要内嵌图片时心里立刻有数。
带宽规划小抄
- 先量原始载荷(
Content-Length或文件字节)。 - 乘以
4/3(或直接看工具的膨胀 %)。 - 加上外框:Data URI 的 MIME 前缀、JSON 引号/转义、multipart 边界。
- 确认线上是否还有 gzip/brotli——压缩后的 Base64 往往接近原文大小,但 CPU 与缓存行为仍会变。
- 数兆级二进制优先 multipart 或原始 body;Base64 留给小 token、PEM,以及只能走纯文本通道的内嵌场景。
FAQ
为什么 Base64 会让体积变大(size increase)?
因为 Base64 固定把 3 字节 → 4 字符,大文件开销约 (4−3)/3 ≈ 33.3%。极短输入会因填充涨得更多(例如 2 字节 → 4 字符 = 100%)。
Base64 算压缩吗?能抵消这 33% 吗?
不算。Base64 是编码不是压缩。传输时再做 gzip 可能把线上流量压回去,但编码后的逻辑体积仍然大约大了三分之一。
怎么在线量一下 Base64 体积膨胀?
把数据贴进 Base64 编解码工具 对比长度,或用 图片转 Base64 看图片编码后涨多少。全程浏览器本地处理。
排查注记
三个例子从 2 字节到 1MB 是按反直觉程度选的:"Hi" 膨胀 100% 正是开篇点破的短数据陷阱,1MB 才收敛到教科书说的 33.4%——文件越大越接近理论值,所以短数据值得单独算账。n mod 3 的填充表解释了开销区间的来源(33% 到 300%),也回答了为什么同是 5 字节的 Hello 是 60%。「什么时候可以忽略」一节里 gzip 那条最常被漏掉:Base64 后再压缩通常能压回接近原始大小,开了压缩的传输几乎不用为 Base64 付净增成本。
来自 ToolVault 工具匣 的开发手记。相关阅读:Base64 编码详解。