📝 博客 · 2026-07-29 · ⏱ 8 分钟

Base64编码是什么?一看就懂

用最简单的方式讲清楚 Base64 的原理、为什么叫 Base64、它和加密的区别,以及常见的使用场景。

一、Base64 是什么

先看一段看起来像乱码的字符串:

SGVsbG8gV29ybGQ=

把它丢进任何 Base64 解码器里,会得到一句话:

Hello World

这就是 Base64——一种把任意二进制数据用 64 个可打印字符表示的编码方式。它的本质是"换一种写法",而不是加密。

那为什么要"换一种写法"?因为早期的很多系统(比如邮件、HTTP、HTML)只能安全地传输 ASCII 字符。如果你直接把一张图片(二进制)塞进邮件里,中间经过的路由器、网关很可能把一些控制字符吃掉,导致接收方拿到的就是损坏的数据。

Base64 的解决办法很简单:把二进制重新编码成纯文本,这样无论经过哪里都不会出问题。

二、为什么叫"Base64"

名字里的 "64",指的是它用了 64 个字符作为"基本字母表":

编号字符范围实际字符
0-25大写字母A B C ... Z
26-51小写字母a b c ... z
52-61数字0 1 2 ... 9
62特殊字符+
63特殊字符/
填充占位符=(末尾补齐用)

为什么是 64 而不是 32 或者 128?因为 64 = 2^6,每 6 位二进制正好对应一个字符。而 6 和 8(一字节 8 位)的最小公倍数是 24,所以每 3 个字节(24 位)可以整齐地拆成 4 个 6 位,对应 4 个 Base64 字符。

三、编码原理:3 字节变 4 字符

这是 Base64 最核心的一步。我们用 "Man" 这三个字符来举例。

第一步,把每个字符转成 ASCII 码:

字符ASCII(十进制)二进制
M7701001101
a9701100001
n11001101110

第二步,把这 3 个字节拼成 24 位:

01001101 01100001 01101110

第三步,每 6 位切一刀,切成 4 组:

010011 010110 000101 101110

第四步,每组转成十进制,再查 Base64 字母表:

二进制十进制对应字符
01001119T
01011022W
0001015F
10111046u

所以 "Man" 的 Base64 编码就是 TWFu

如果原始字节数不是 3 的倍数,最后会补 0 凑齐 6 位,并在结果末尾用 = 补齐到 4 的倍数长度。这就是为什么你经常看到 Base64 字符串末尾有 1 个或 2 个 =

四、URL 安全的 Base64

标准 Base64 里有两个字符在 URL 里会出问题:

所以有了"URL Safe Base64",把这两个字符换掉:

标准字符URL 安全字符
+-
/_

末尾的 = 通常也会去掉。JWT(JSON Web Token)里用的就是 URL Safe Base64,因为 token 要放在 URL 或 HTTP 头里传输。

五、Base64 的常见使用场景

场景说明
邮件附件MIME 协议规定附件必须用 Base64 编码后嵌入邮件正文
图片内嵌到 HTML把小图标编码成 data:image/png;base64,xxxx,省一次 HTTP 请求
Data URLCSS 里直接写 background: url(data:image/svg;base64,...)
JWTHeader 和 Payload 都用 Base64URL 编码
HTTP Basic Auth用户名密码用 Authorization: Basic 发送
数据库存储二进制某些 NoSQL 数据库只支持字符串,二进制要先 Base64 编码
配置文件把证书、密钥等二进制内容塞进 JSON/YAML 配置里

举个例子,下面是一张 1x1 透明 PNG 内嵌到 HTML 的写法:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVR4nGNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=" />

这样图片就不需要额外的网络请求,直接跟着 HTML 一起下载了。

六、Base64 不是加密

这是一个非常常见的误解。Base64 编码后的字符串看起来像加密,但实际上:

它的设计目标只是"让二进制能安全通过文本通道传输",根本不是为了保密。如果你把密码用 Base64 编码后存到数据库里,等同于明文存储——任何人执行一句 echo xxx | base64 -d 就能看到原文。

下面的代码可以让你直观感受到这一点:

import base64

# 编码
encoded = base64.b64encode(b"password123")
print(encoded)  # b'cGFzc3dvcmQxMjM='

# 解码
decoded = base64.b64decode(encoded)
print(decoded)  # b'password123'

整个过程中没有任何密钥参与,"解密"也就是一行代码的事。

七、Base64 的代价

Base64 不是免费的午餐,它有一个明显的代价:体积会变大 1/3 左右

因为每 3 个字节会被编码成 4 个字符,所以一段 300KB 的二进制数据,Base64 编码后会变成大约 400KB。在带宽敏感的场景(比如大量图片内嵌到 HTML)需要权衡:

八、实践推荐

日常开发中遇到 Base64 的场景非常多——解码接口返回的图片、查看 JWT 内容、把小图标内嵌到 CSS 里等等。手写脚本太麻烦,直接用在线工具最快:

支持文本和文件互转、URL Safe 模式切换、实时预览解码结果,调试接口和配置文件时非常方便。