URL 编码(百分号编码)完全指南
发布日期:2026年6月22日 | 阅读时间:7分钟
你是否遇到过这样的情况:URL 中的中文参数变成了看不懂的乱码,或者精心构造的 API 请求因为特殊字符而失败?这些问题的根源都在于 URL 编码。本文将彻底讲清楚 URL 编码的一切。
为什么需要 URL 编码?
URL(统一资源定位符)在设计之初只允许使用 ASCII 字符集中的部分字符。具体来说,URL 只能安全地包含:
- 英文字母:A-Z, a-z
- 数字:0-9
- 少数特殊字符:- _ . ~
任何超出这个范围的字符——包括中文、空格、&、=、# 等——都必须经过编码才能安全地放入 URL 中。这个编码过程就是 URL 编码,也叫百分号编码(Percent Encoding)。
URL 编码的原理
URL 编码的规则非常简单:将每个需要编码的字符转换为它的 UTF-8 字节序列,然后将每个字节表示为 %XX 的格式,其中 XX 是字节的十六进制值。
示例:空格
原始字符: 空格
ASCII 码: 32
十六进制: 20
URL 编码: %20(传统形式)或 +(表单编码形式)
示例:中文字符
原始字符: 你
UTF-8 编码: E4 BD A0(3个字节)
URL 编码: %E4%BD%A0
这就是为什么中文 URL 会变成一长串 % 开头的东西——每个中文字符在 UTF-8 中占 3 个字节,编码后就变成了 3 个 %XX。
JavaScript 中的 URL 编码
JavaScript 提供了三个编码函数,它们的行为有微妙但重要的差异:
encodeURIComponent():编码一切
编码除了字母、数字和 - _ . ! ~ * ' ( ) 之外的所有字符。这是编码 URL 参数值的正确选择:
encodeURIComponent("你好 world!")
// → "%E4%BD%A0%E5%A5%BD%20world!"
// 空格→%20,中文→UTF-8字节的%形式,! 被保留
encodeURI():保留 URL 结构
与 encodeURIComponent 类似,但会保留 URL 中的特殊字符(如 / ? & = #)。适合编码完整的 URL而非单个参数:
encodeURI("https://example.com/搜索?q=你好")
// → "https://example.com/%E6%90%9C%E7%B4%A2?q=%E4%BD%A0%E5%A5%BD"
// / ? = 等 URL 结构字符被保留,中文路径被编码
escape():已废弃,不要用
旧的编码函数,不处理 + @ / 等字符,且编码方式与现代标准不同。绝对不要在新代码中使用。
速查表
| 场景 | 使用 | 示例 |
|---|---|---|
| 编码 URL 参数值 | encodeURIComponent() | ?q=你好 |
| 编码完整 URL | encodeURI() | https://... |
| 编码路径段 | encodeURIComponent + 手动替换%2F | /users/张三 |
最常见的 URL 编码错误
错误 1:用 encodeURI 编码参数值
// ❌ 错误:& 和 = 不会被编码
const url = "https://api.com/search?q=" + encodeURI("a=1&b=2");
// 结果: https://api.com/search?q=a=1&b=2
// 服务器会解析成两个参数:q=a 和 b=2
// ✅ 正确
const url = "https://api.com/search?q=" + encodeURIComponent("a=1&b=2");
// 结果: https://api.com/search?q=a%3D1%26b%3D2
错误 2:重复编码
// ❌ 对已经编码的值再次编码
const encoded = encodeURIComponent("你好"); // %E4%BD%A0%E5%A5%BD
const doubleEncoded = encodeURIComponent(encoded); // %25E4%25BD...
// % 被编码成了 %25!
// ✅ 解码前先检查是否已被编码
function safeDecode(str) {
try {
return decodeURIComponent(str);
} catch {
return str; // 已经不是合法的编码格式
}
}
错误 3:混淆 application/x-www-form-urlencoded 和 URL 编码
表单数据的编码格式和 URL 的编码格式不是同一回事:
- URL 编码:空格编码为 %20
- 表单编码:空格编码为 +(历史原因)
如果你的后端期望 x-www-form-urlencoded 格式,你需要确保空格被编码为 + 而非 %20。
实战场景
1. 构建带查询参数的 API URL
function buildURL(base, params) {
const query = Object.entries(params)
.map(([k, v]) => encodeURIComponent(k) + '=' + encodeURIComponent(v))
.join('&');
return base + '?' + query;
}
buildURL("https://api.com/search", {
q: "Vue.js 教程", // → q=Vue.js%20%E6%95%99%E7%A8%8B
page: 1,
sort: "created_at"
});
2. RESTful API 中的中文路径
// ❌ 直接拼接,可能产生非法 URL
fetch(`/users/${username}`); // username = "张三"
// ✅ 对路径段编码
fetch(`/users/${encodeURIComponent(username)}`);
// → /users/%E5%BC%A0%E4%B8%89
3. 在 HTML 属性中使用 URL
// href 中的 & 必须转义为 &
<a href="/search?q=vue&page=2">Next</a>
// 但 JavaScript 中不需要
element.href = "/search?q=vue&page=2"; // ✅ 正确
HTML 实体编码 vs URL 编码
这是两种完全不同的编码,千万别搞混:
- URL 编码:用于 URL 参数,使用 %XX 格式
- HTML 实体编码:用于 HTML 文档,使用 &name; 或 &#number; 格式。目的是防止 XSS 攻击和在 HTML 中正确显示特殊字符
在 HTML 的 href 属性中,这两种编码可能会同时出现,理解它们的区别至关重要。
使用我们的 URL 编解码工具
在线 URL 编解码器支持:
- URL 百分号编码和解码
- Unicode 转义序列处理
- HTML 实体编解码
- 完全在浏览器本地运行
立即体验:使用 URL 编解码器
总结
- URL 编码(百分号编码)将非 ASCII 和特殊字符转为 %XX 格式
- 编码参数值用 encodeURIComponent,编码完整 URL 用 encodeURI
- 最常见的坑是重复编码和用错函数
- URL 编码和 HTML 实体编码是两回事,不要混淆
本文最后更新于 2026年6月26日