Base64 vs URL 编码
了解 Base64 编码和 URL 编码的区别,以及各自的适用场景。它们解决的是不同的问题——用错了是 bug 的常见来源。
什么是 Base64 编码?
Base64 将任意二进制数据编码为可打印 ASCII 字符的字符串。它将每 3 个字节的输入转换为 4 个字符,字符取自 64 个字符的字母表:A–Z、a–z、0–9、+ 和 /。填充字符(=)将输出对齐为 4 的倍数。
输出始终比输入大约 33%。Base64 不包含任何关于数据含义的信息——它纯粹是一种传输编码,用于在基于文本的系统(如 HTTP 请求头、JSON、XML 和邮件)中传递二进制数据。
示例——将 "Hello" 编码为 Base64
// JavaScript
btoa('Hello')
// → "SGVsbG8="
// For non-ASCII text, use TextEncoder first:
const bytes = new TextEncoder().encode('Hello 🌍')
let binary = ''
bytes.forEach(b => binary += String.fromCharCode(b))
btoa(binary)
// → "SGVsbG8g8J+MjQ=="示例——对查询字符串进行 URL 编码
// JavaScript
encodeURIComponent('C++ & "Go"')
// → "C%2B%2B%20%26%20%22Go%22"
// Build a safe query string:
const params = new URLSearchParams({
q: 'hello world',
lang: 'C++',
})
params.toString()
// → "q=hello+world&lang=C%2B%2B"
// Decode:
decodeURIComponent('C%2B%2B')
// → "C++"什么是 URL 编码?
URL 编码(又称百分号编码)将 URL 中不允许使用或具有特殊含义的字符替换为 % 加两位十六进制数字。空格变为 %20, < 变为 %3C,/ 变为 %2F。
标准 ASCII 字母和数字不会被改变。开销因内容而异——纯英文句子变化很小,但充满符号或非 ASCII 字符的字符串体积可能增加为原来的三倍。URL 编码由 RFC 3986 定义。
核心区别
| 对比项 | Base64 | URL 编码 |
|---|---|---|
| 主要用途 | 将二进制数据转换为 ASCII 文本 | 转义 URL 中的特殊字符 |
| 常见使用场景 | 图片、文件、API、Data URI、邮件 | 查询字符串、表单数据、URL 路径段 |
| 输出字符 | A–Z、a–z、0–9、+、/、=(填充) | %20、%3C、%2F、+(查询中的空格) |
| 体积开销 | 比输入大约 33%(固定比例) | 不固定——ASCII 字符不变,其他字符变为 3 倍 |
| 适合二进制文件 | 是——专为二进制数据设计 | 否——处理原始二进制不实际 |
| 适合 URL 参数 | 不直接适合(+ 和 / 是保留字符) | 是——这正是它的用途 |
| 人类可读性 | 否——输出不透明 | 部分——ASCII 文本保持可读 |
| 解码方式 | atob() / Buffer.from(str, "base64") | decodeURIComponent() / urllib.parse |
何时使用 Base64
在 HTML 或 CSS 中嵌入图片
Data URI 允许将图片数据直接内联到 src 或 background-image 中,无需额外的 HTTP 请求。
src="data:image/png;base64,iVBORw0K..."在 JSON API 载荷中发送文件
JSON 只能传输文本。当 multipart/form-data 不可用时,Base64 是在 JSON 请求体中包含文件内容的标准方式。
{ "content": "SGVsbG8gV29ybGQ=" }邮件附件和内联图片
MIME 邮件使用 Base64 对附件和 CID 引用的图片进行编码,确保二进制数据能安全地通过基于文本的邮件服务器传输。
Content-Transfer-Encoding: base64将二进制数据存储为文本
数据库、配置文件和环境变量都是基于文本的。Base64 是存储二进制内容(密钥、证书、图标)的惯用方式。
CERT="LS0tLS1CRUdJTi..."何时使用 URL 编码
查询字符串参数
URL 查询字符串中传递的任何值都必须进行百分号编码,以防止 ?、&、= 和 # 等字符破坏 URL 结构。
/search?q=hello+world&tag=c%2B%2B表单提交(application/x-www-form-urlencoded)
HTML 表单 POST 请求体默认使用 URL 编码。浏览器在发送前会对字段名和值进行编码。
name=Tom+Hanks&city=New+York对用户提供的路径段进行编码
如果文件名或用户输入的字符串成为 URL 路径的一部分,需对其编码以防止路径遍历和链接失效。
/files/my%20report%20(final).pdf分享含特殊字符的链接
URL 中的空格、带重音的字符和符号必须编码,以确保其在复制粘贴、邮件和 HTTP 请求头中保持完整。
/fr/caf%C3%A9-menuSVG 示例:Base64 vs URL 编码
SVG 图像可以用两种方式嵌入到 CSS 或 HTML 中。对于小型 SVG,URL 编码通常更紧凑,因为 SVG 标记主要是 ASCII 文本。
Base64 方式
/* CSS */ background-image: url( "data:image/svg+xml;base64, PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My..." );
URL 编码方式
/* CSS */ background-image: url( "data:image/svg+xml,%3Csvg%20xmlns%3D %27http%3A%2F%2Fwww.w3.org%2F2000..." );
两种方式都可用。对于含非 ASCII 字符或嵌入字体的 SVG,可分别测试并选择更小的那种。 试试 SVG 转 Base64 工具 →
API 示例:该用哪种?
API 两者都会用到。在 JSON 请求体中携带文件内容时使用 Base64;从用户输入构建查询字符串或路径段时使用 URL 编码。
用 Base64——在 JSON 请求体中传文件
JSON 只能传文本。Base64 是在其中嵌入二进制文件内容的方式。
fetch('/api/upload', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
filename: 'avatar.png',
content: 'iVBORw0KGgoAAAANSUhEUgAA...',
}),
})用 URL 编码——GET 请求中的筛选参数
查询字符串中用户提供的值必须经过 URL 编码才安全。
const params = new URLSearchParams({
q: 'C++ developer',
location: 'San Francisco, CA',
type: 'full-time',
})
fetch('/api/jobs?' + params.toString())
// → /api/jobs?q=C%2B%2B+developer&...需要在 JSON 中发送文件? 试试 Base64 API 上传工具 →
需要在 URL 中使用 Base64?请用 Base64URL
标准 Base64 使用 +、/ 和 =——这些在 URL 中都是保留字符。Base64URL 将它们替换为 -、_,并去掉填充符。广泛用于 JWT、OAuth token 和现代 API。
常见问题
Base64 和 URL 编码是同一回事吗?
不是。Base64 使用 64 个字符的字母表将二进制数据转换为文本字符串。URL 编码(百分号编码)将 URL 中有特殊含义的字符替换为 % 加两位十六进制数字。它们解决的是不同的问题,不可互换使用。
可以在 URL 查询字符串中使用 Base64 吗?
标准 Base64 包含 + 和 /,这两个字符在 URL 中是保留字符,会被误解析。请改用 Base64URL——它将 + 替换为 -,/ 替换为 _,并去掉 = 填充符。Base64URL 字符串无需任何额外编码即可安全用于 URL。
URL 编码就是 Base64 吗?
不是。URL 编码(百分号编码)完全不同。它将每个字符替换为 % 前缀加两位十六进制数字——例如空格变为 %20,< 变为 %3C。Base64 则使用 64 个字符的字母表对整个二进制序列进行编码。
Base64 和 URL 编码哪个更高效?
取决于内容。Base64 始终增加约 33% 的开销,与输入无关。URL 编码只对需要转义的字符进行编码——URL 中的纯 ASCII 文本长度不变。对于二进制数据,Base64 远比 URL 编码高效,因为每个原始字节在 URL 编码后都会变成三字符的 %XX 序列。
Base64URL 是什么,它与 Base64 有何不同?
Base64URL 是 Base64 的 URL 安全变体。它将 + 替换为 -,/ 替换为 _,并省略 = 填充符。这使输出无需百分号编码即可安全用于 URL 和文件名。JWT 和许多现代 API 都使用 Base64URL。
SVG 可以同时用 Base64 和 URL 编码嵌入吗?
可以。在 CSS background-image 或 HTML src 中,SVG 可以作为 Base64 Data URI(data:image/svg+xml;base64,...)或 URL 编码 Data URI(data:image/svg+xml,...)嵌入。对于 SVG,URL 编码通常更紧凑,因为 SVG 主要是 ASCII 文本,大多数字符不需要转义。