一、什么是URL编码

URL编码(URL Encoding),也称为百分号编码(Percent-encoding),是一种将非ASCII字符或特殊字符转换为可在URL中安全传输的格式的机制。

为什么需要URL编码?

  • URL 只能包含 ASCII 字符,但实际数据常包含中文、空格、特殊符号等。
  • 对保留字符(如 ?&)若不作为分隔符使用,必须编码以防解析歧义。
  • 例如,中文“上海+中國”编码后为 %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B

二、编码规则

遵循 RFC 3986 标准,URL 字符分为保留字符和未保留字符。

✅ 未保留字符(无需编码)
  • 字母:A-Z a-z
  • 数字:0-9
  • 特殊符号:- _ . ~
⚠️ 保留字符(需编码)
  • : / ? # [ ] @
  • ! $ & ' ( ) *
  • + , ; =

编码方法:

  • ASCII 字符:将字符的 ASCII 值转为两位十六进制,前加 %,如 /%2F
  • 非 ASCII 字符(如中文):先用 UTF-8 编码为字节序列,再对每个字节做百分号编码。
  • 百分号本身:%%25

三、全部字符编码表(ASCII 可打印字符)

下表列出了 ASCII 码 32~126 的所有可打印字符及其 URL 百分号编码。控制字符(0~31、127)通常不直接出现在 URL 中,如需编码也遵循 %XX 格式(如换行 %0A)。

字符 十进制 十六进制 URL 编码 字符 十进制 十六进制 URL 编码
加载中...

四、常见非ASCII字符(UTF-8)编码示例

字符 Unicode 码点 UTF-8 字节 URL 编码
U+4E2DE4 B8 AD%E4%B8%AD
U+6587E6 96 87%E6%96%87
U+4F60E4 BD A0%E4%BD%A0
U+597DE5 A5 BD%E5%A5%BD
🚀U+1F680F0 9F 9A 80%F0%9F%9A%80
U+20ACE2 82 AC%E2%82%AC

五、空格编码的特殊说明

场景编码说明
URL 路径 / 查询参数(RFC 3986)%20现代标准推荐方式
application/x-www-form-urlencoded(表单提交)+HTML 表单默认使用
💡 建议: 在编码 URL 时,使用 %20 表示空格,用 %2B 表示加号 +,这样可以避免歧义。

六、编程实现

JavaScript
// 编码完整URL
encodeURI("https://example.com/搜索?q=hello world")
// → "https://example.com/%E6%90%9C%E7%B4%A2?q=hello%20world"

// 编码组件(查询参数)
encodeURIComponent("文件/name")
// → "%E6%96%87%E4%BB%B6%2Fname"

// 解码
decodeURIComponent("%21%40") // "!@"
Python
from urllib.parse import quote, unquote

# 编码
quote("搜索!@#", safe="")
# → '%E6%90%9C%E7%B4%A2%21%40%23'

# 解码
unquote("%E6%96%87%E4%BB%B6")
# → '文件'
PHP
// rawurlencode (RFC 3986)
rawurlencode("hello world");
// → "hello%20world"

// urlencode (表单,空格变+)
urlencode("hello world");
// → "hello+world"

七、注意事项

  • 避免多次编码/解码:多次编码会导致 %2520 这样的嵌套,需谨慎。
  • 非ASCII字符统一使用UTF-8
  • 保留字符的差异化处理encodeURI() 不编码 ; , / ? : @ & = + $encodeURIComponent() 全部编码。
  • 安全考虑:服务器端需在解码后校验参数,防止绕过过滤。

八、总结

URL编码(百分号编码)的核心规则:

  • 未保留字符(字母、数字、-_.~)不编码。
  • 保留字符和非ASCII字符编码为 % + 两位十六进制。
  • 非ASCII字符先转UTF-8再逐字节编码。
  • 空格在RFC 3986中为 %20,表单中可为 +

掌握URL编码,避免解析错误与乱码,确保数据传输安全。