跳到主要内容
编码转换2026-09-135 分钟阅读

为什么 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填充 = 数量编码后长度实际开销
004n/333.3%
124(n+2)/333% - 300%
214(n+1)/333% - 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 是变体:

标准 Base64Base64URL
+-
/_
=(填充)通常去掉

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 响应大小、判断要不要内嵌图片时心里立刻有数。

带宽规划小抄

  1. 先量原始载荷(Content-Length 或文件字节)。
  2. 乘以 4/3(或直接看工具的膨胀 %)。
  3. 加上外框:Data URI 的 MIME 前缀、JSON 引号/转义、multipart 边界。
  4. 确认线上是否还有 gzip/brotli——压缩后的 Base64 往往接近原文大小,但 CPU 与缓存行为仍会变。
  5. 数兆级二进制优先 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 编码详解。