URL 编码(也称为百分号编码,Percent-Encoding)是一种将字符转换为可在 URL 中安全传输的格式的编码机制。根据 RFC 3986 规范,URL 中只允许包含有限的 ASCII 字符子集,包括大小写字母、数字以及少量特殊符号(如连字符、下划线、句点和波浪号)。当 URL 中需要出现中文字符、空格、标点符号或其他不在安全字符集中的字符时,就必须使用 URL 编码将其转换为 % 后跟两位十六进制数的形式。例如空格会被编码为 %20,中文字符"中"会被编码为 %E4%B8%AD。URL 编码是 Web 开发中处理地址栏参数、API 请求、表单提交等场景的基础知识,理解其规则有助于避免各种编码相关的错误。
URL 编码的核心思想很简单:将不安全的字符转换为一个百分号(%)加上该字符在 UTF-8 编码下的十六进制表示。但并非所有字符都需要编码,RFC 3986 将 URL 中的字符分为三类:
保留字符在 URL 中具有特殊含义,用于分隔 URL 的各个组成部分。它们包括:
: / ? # [ ] @ ! $ & ' ( ) * + , ; =
这些字符是否需要编码取决于它们出现的位置。例如,/ 在路径中是分隔符,不应被编码;但如果 / 出现在查询参数的值中,就必须编码为 %2F,否则会被误认为路径分隔符。
以下字符在 URL 中没有特殊含义,但由于各种原因(可能与网关、代理等中间设备的处理冲突)被认为是不安全的,应当始终进行编码:
空格 " < > # % { } | \ ^ ~ [ ] `
其中空格是最常见的不安全字符。在 URL 的路径部分,空格会被编码为 %20;而在查询字符串中,某些规范和历史惯例也允许用加号 + 代替空格。
所有不在 ASCII 范围内的字符(如中文、日文、韩文、Emoji 等)必须先转换为 UTF-8 字节序列,然后对每个字节进行百分号编码。例如"你好"的 UTF-8 编码为 E4 BD A0 E5 A5 BD,因此 URL 编码后为 %E4%BD%A0%E5%A5%BD。这也是为什么一个中文字符会被编码为三个 %XX 序列的原因。
URL 编码在 Web 开发和网络通信中无处不在,以下是几个典型的应用场景:
> 需要编码为 %3E,否则浏览器可能无法正确解析 URL 结构。/images/产品照片.jpg,必须编码为 /images/%E4%BA%A7%E5%93%81%E7%85%A7%E7%89%87.jpg,否则服务器可能无法正确找到该资源。application/x-www-form-urlencoded 格式提交数据时,所有字段名和字段值都会被自动进行 URL 编码。空格被替换为 +,其他特殊字符按规则编码。URL 编码和 Base64 编码虽然都是字符编码方式,但它们的设计目的和适用场景完全不同:
| 对比维度 | URL 编码(百分号编码) | Base64 编码 |
|---|---|---|
| 设计目的 | 让特殊字符在 URL 中安全传输 | 将二进制数据转换为 ASCII 文本格式 |
| 编码方式 | 逐字符转换为 %XX 或 %XX%XX%XX |
每 3 字节转换为 4 个 Base64 字符 |
| 输出字符集 | 使用十六进制数字(0-9, A-F)和 % |
使用 A-Z, a-z, 0-9, +, / |
| 数据膨胀 | ASCII 字符不膨胀,中文膨胀为 3 倍 | 固定膨胀约 33% |
| 可逆性 | 完全可逆 | 完全可逆 |
| 典型用途 | URL 参数、路径、表单数据 | Email 附件、Data URI、JWT、API 认证 |
简单来说,URL 编码是让字符"适应"URL 格式的安全机制,而 Base64 编码是让二进制数据"伪装"成文本的转换方式。两者解决的问题不同,不应混淆使用。
以下是一些在日常开发中经常需要编码的字符及其对应的 URL 编码结果,供快速查阅:
| 字符 | 说明 | URL 编码结果 |
|---|---|---|
| (空格) | 空格字符 | %20 |
| ! | 感叹号 | %21 |
| " | 双引号 | %22 |
| # | 井号(锚点标记) | %23 |
| $ | 美元符号 | %24 |
| % | 百分号本身 | %25 |
| & | 和号(参数分隔符) | %26 |
| ' | 单引号 | %27 |
| ( | 左括号 | %28 |
| ) | 右括号 | %29 |
| * | 星号 | %2A |
| + | 加号 | %2B |
| , | 逗号 | %2C |
| / | 斜杠(路径分隔符) | %2F |
| : | 冒号 | %3A |
| ; | 分号 | %3B |
| = | 等号(键值分隔符) | %3D |
| ? | 问号(查询起始符) | %3F |
| @ | @ 符号 | %40 |
| 中 | 中文字符"中" | %E4%B8%AD |
| 好 | 中文字符"好" | %E5%A5%BD |
这是历史上两个不同规范导致的兼容性问题。%20 是 RFC 3986 规定的标准 URL 编码方式,适用于 URL 的所有部分。而 + 代表空格来自 application/x-www-form-urlencoded 格式(HTML 表单默认的提交格式),该格式最初的设计是为了在编码后的数据中节省空间。因此,在处理查询参数时,你会看到空格有时被编码为 %20,有时被编码为 +。在解码时,需要同时处理这两种情况。本工具的解码功能会自动将 + 还原为空格。
双重编码是指对已经编码过的字符串再次进行编码。例如,空格第一次编码后变成 %20,如果再次编码,% 会被编码为 %25,结果变成 %2520。这通常是一个编程错误,会导致解码后得到原始编码字符串而非原始文本。双重编码常见于参数经过多层传递(如前端 → 后端 → 重定向 → 另一个服务)时没有正确解码就再次编码的情况。调试时如果看到类似 %25XX 的模式,很可能就是双重编码。解决方法是确保每一层只在需要时编码一次,并在使用前正确解码。
JavaScript 提供了两个 URL 编码函数,它们的区别在于编码范围不同。encodeURI() 不会编码 URL 的保留字符(如 : / ? # & = 等),因此它适合对完整的 URL 进行编码,保留 URL 的结构分隔符不被破坏。encodeURIComponent() 则会编码所有保留字符(除了字母、数字、- _ . ! ~ * ' ( )),适合对 URL 的组成部分(如查询参数的值)进行编码。举个例子,对于字符串 a=b&c=d:encodeURI 不会编码 = 和 &,而 encodeURIComponent 会将它们分别编码为 %3D 和 %26。在实际开发中,绝大多数场景应该使用 encodeURIComponent,只有在编码整个 URL 时才使用 encodeURI。
几乎所有主流编程语言都内置了 URL 编码与解码函数,但它们的命名、行为和编码范围各有差异,跨语言协作时需要特别注意:
encodeURIComponent() 和 encodeURI() 两个函数,前者编码范围更广,适合编码查询参数的值;后者保留 URL 结构字符,适合编码整条 URL。对应解码函数为 decodeURIComponent() 和 decodeURI()。urllib.parse 提供 quote() 和 unquote()。其中 quote(string, safe='') 的 safe 参数用于指定不编码的字符,默认斜杠会被编码,需根据场景调整。java.net.URLEncoder.encode(str, "UTF-8") 会将空格编码为加号 +(遵循表单规范),URLDecoder.decode() 用于解码,务必显式指定 UTF-8 字符集以避免乱码。urlencode()(空格变加号)或 rawurlencode()(空格变 %20,遵循 RFC 3986),解码分别对应 urldecode() 和 rawurldecode()。net/url 包提供 QueryEscape()(空格变加号)和 PathEscape()(空格变 %20),分别适用于查询字符串和路径段。在实际开发中遵循以下规范,可以避免绝大多数编码相关的问题:
&、=、/ 等结构分隔符编码,否则会破坏 URL 的语法。推荐使用各语言提供的查询字符串构建工具(如 Python 的 urlencode()、JavaScript 的 URLSearchParams)来避免手动拼接出错。%25 开头的编码通常意味着发生了双重编码。简单口诀:编码完整 URL 用 encodeURI,编码 URL 的某个组成部分(尤其是查询参数值)用 encodeURIComponent。绝大多数业务场景下你应该使用 encodeURIComponent,因为它会编码 &、=、? 等字符,确保参数值中的特殊字符不会与 URL 结构混淆。错误地使用 encodeURI 编码参数值,是导致参数被截断或解析异常的常见原因。
这个错误通常出现在 JavaScript 的 decodeURIComponent() 中,原因是输入字符串里存在不完整的百分号编码序列。例如孤立的 % 后面没有跟两位十六进制数,或者 % 后跟的是非十六进制字符(如 %GG),都会导致解码失败。此外,被截断的 UTF-8 序列(如中文编码 %E4%B8 缺少了第三个字节)也会触发此错误。排查时应检查输入是否被意外截断、是否存在二次编码后的异常字符,或是混入了非标准编码(如 GBK 编码的中文被当作 UTF-8 解码)。本工具在解码失败时会给出明确提示,便于你快速定位问题所在。
使用本工具进行 URL 编码和解码非常简单:
本工具采用 UTF-8 编码,能够正确处理中文字符、日文字符、Emoji 以及各类特殊符号的 URL 编码和解码。所有操作均在浏览器本地完成,不会将您的数据发送到任何服务器,充分保障数据隐私安全。