参考6 分钟阅读

URL 编码与 Base64 编码:有什么区别?

URL 编码(百分号编码)依据 RFC 3986 将 URL 中的特殊字符转换为 %XX 格式。Base64 编码依据 RFC 4648 使用 64 个 ASCII 字符将二进制数据转换为文本字符串。二者用途不同,不能相互替代。

什么是 URL 编码?

URL 编码,也称为百分号编码,由 RFC 3986 定义,是一种用于表示 URI 中不被允许或具有特殊含义的字符的机制。每个需要编码的字符会被转换为一个或多个字节(使用 UTF-8),而每个字节则表示为一个百分号(%)后跟两位大写十六进制数字。

例如,空格字符会变成 %20,&符号会变成 %26,而像欧元符号这样的非 ASCII 字符则会变成 %E2%82%AC(三个 UTF-8 字节,每个都经过百分号编码)。

// JavaScript 中的 URL 编码示例
encodeURIComponent('hello world');   // "hello%20world"
encodeURIComponent('price=10&qty=2'); // "price%3D10%26qty%3D2"
encodeURIComponent('cafe');         // "caf%C3%A9"

URL 编码专门用于确保 URL 安全且有效。它只对 URI 中不被允许或具有保留含义的字符进行编码,而字母数字字符以及少数几个安全符号则保持不变。

什么是 Base64 编码?

Base64 编码由 RFC 4648 定义,是一种二进制到文本的编码方案,它使用一组 64 个 ASCII 字符来表示二进制数据:A-Za-z0-9+/,并用 = 进行填充。每三个字节的输入会产生四个字符的输出。

Base64 的设计初衷是在那些只能可靠支持文本的通道上传输二进制数据,例如电子邮件(MIME),或将数据嵌入 XML/JSON 中。它并非专门针对 URL,并且会对所有输入字节进行编码,而不仅仅是特殊字符。

// JavaScript 中的 Base64 编码示例
btoa('hello world');         // "aGVsbG8gd29ybGQ="
btoa('price=10&qty=2');      // "cHJpY2U9MTAmcXR5PTI="

// 对于 Unicode 字符串,需先编码为 UTF-8
function toBase64(str) {
  return btoa(unescape(encodeURIComponent(str)));
}
toBase64('cafe');           // "Y2Fmw6k="

此外还有一种 URL 安全的 Base64 变体(Base64url),它将 + 替换为 -,将 / 替换为 _,并且通常省略 = 填充。这种变体用于 JWT、URL 中的 data URI 以及其他标准 Base64 字符会与 URL 语法冲突的场景。

主要区别

特性 URL 编码 Base64 编码
标准 RFC 3986 RFC 4648
用途 使 URL 安全 以文本表示二进制
编码对象 仅特殊/保留字符 所有输入字节
输出格式 %XX 十六进制序列 A-Z、a-z、0-9、+、/、=
体积增长 可变(仅被编码的字符增长) 始终增大约 33%
可逆
人类可读 部分可读(非保留字符保持不变)
默认 URL 安全 是(设计使然) 否(包含 +、/、=)

何时使用哪种编码

使用 URL 编码,当你需要在 URL 中包含特殊字符时,例如查询参数值、路径段或片段标识符。对于任何数据必须嵌入 URL 结构的情况,URL 编码都是正确的选择。

使用 Base64 编码,当你需要将二进制数据(图片、文件、加密载荷)表示为文本、在 JSON 或 XML 中嵌入二进制内容,或通过纯文本通道传输数据时。Base64 还用于 HTTP 基本认证(Basic Authentication)头部和 JSON Web Token(JWT)。

// URL 编码:将搜索词嵌入 URL
const searchUrl = 'https://example.com/search?q=' +
  encodeURIComponent('C++ & Java');
// "https://example.com/search?q=C%2B%2B%20%26%20Java"

// Base64:在 CSS 或 HTML 中嵌入图片
const imageData = 'data:image/png;base64,iVBORw0KGgoAAAANS...';

// Base64:HTTP 基本认证头部
const credentials = btoa('username:password');
const header = 'Authorization: Basic ' + credentials;

可以将二者结合使用吗?

可以,而且在某些情况下必须结合使用。如果你需要将 Base64 编码的数据作为 URL 参数传递,标准的 Base64 输出可能包含 +/= 字符,而这些字符在 URL 中具有特殊含义。你有两种选择:

方案一: 在将 Base64 字符串放入 URL 之前先对其进行 URL 编码。+ 会变成 %2B/ 会变成 %2F= 会变成 %3D

方案二: 使用 Base64url 变体(RFC 4648 第 5 节),它将 + 替换为 -,将 / 替换为 _,并移除填充。这正是 JWT 和许多现代 API 所采用的方法。

// 方案一:对标准 Base64 进行 URL 编码
const base64 = btoa('binary data here'); // "YmluYXJ5IGRhdGEgaGVyZQ=="
const urlSafe = encodeURIComponent(base64);
// "YmluYXJ5IGRhdGEgaGVyZQ%3D%3D"

// 方案二:Base64url 编码
function toBase64url(str) {
  return btoa(str)
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');
}
toBase64url('binary data here');
// "YmluYXJ5IGRhdGEgaGVyZQ"

相关文章

试用我们的免费工具