ToolPal
屏幕上显示Google搜索引擎主页的特写

URL编码详解 — 你需要了解的一切

📷 Sarah Blocksidge / Pexels

URL编码详解 — 你需要了解的一切

全面学习URL编码(百分号编码),包括保留字符、URL中的UTF-8、常见问题及实用示例。Web开发者的完整参考指南。

D作者: Daniel Park2026年4月3日5分钟阅读

URL编码是什么?

URL编码,也称为百分号编码,是将字符转换为可在URL中安全传输格式的机制。由于URL只能包含ASCII字符集中的有限字符,任何超出此范围的字符,或在URL语法中具有特殊含义的字符,都必须进行编码。

如果你曾在URL中看到%20并好奇它是什么意思,或者曾因包含特殊字符的链接失效而烦恼,本指南将帮助你深入理解URL编码的工作原理及其重要性。

需要快速编码或解码URL?试试我们的URL编码/解码工具 — 它能自动处理所有编码规则。

URL编码存在的原因

URL是在互联网早期设计的,当时系统对字符集的支持非常有限。原始URL规范(1994年发布的RFC 1738)将URL限制为一小部分ASCII字符。这是一个务实的决定,确保URL能够在不同系统、网络和协议间正常工作。

但现实世界需要远不止基本ASCII:

  • 文件名中的空格: 我的文档.pdf需要编码为%E6%88%91%E7%9A%84%E6%96%87%E6%A1%A3.pdf
  • 国际字符: 中文、日文、阿拉伯文等文字需要编码
  • 数据中的特殊字符: 查询参数可能包含&=#等在URL中有特殊含义的字符
  • 二进制数据: 有时需要在URL中包含二进制数据

URL编码通过提供通用的转义机制解决了所有这些问题。

百分号编码的工作原理

百分号编码算法很简单:

  1. 获取要编码的字符
  2. 将其转换为字节表示(非ASCII字符使用UTF-8)
  3. 对每个字节,写入%后跟两位十六进制数字

基本示例

字符UTF-8字节百分号编码
空格0x20%20
!0x21%21
#0x23%23
$0x24%24
&0x26%26
+0x2B%2B
/0x2F%2F
=0x3D%3D
?0x3F%3F
@0x40%40

多字节字符

非ASCII字符在UTF-8中需要多个字节,因此会生成多个百分号编码序列:

字符UTF-8字节百分号编码
é(带重音)0xC3 0xA9%C3%A9
欧元符号0xE2 0x82 0xAC%E2%82%AC
中文(中)0xE4 0xB8 0xAD%E4%B8%AD
日文(か)0xE3 0x81 0x8B%E3%81%8B
表情(笑脸)0xF0 0x9F 0x98 0x80%F0%9F%98%80

用我们的URL编码工具亲自试试这些字符的编码。

URL结构与保留字符

要正确理解URL编码,需要先了解URL结构:

https://user:pass@www.example.com:8080/path/to/page?key=value&foo=bar#section
|_____|  |______| |_______________|____||___________|_________________|_______|
协议    用户信息      主机         端口    路径           查询           片段

保留字符

保留字符在URL中具有特殊含义。如果要将其用作数据(而非分隔符),则必须进行百分号编码。

字符URL中的作用编码形式
:分隔协议、端口、用户信息%3A
/分隔路径段%2F
?开始查询字符串%3F
#开始片段%23
@分隔用户信息和主机%40
&分隔查询参数%26
=在查询中分隔键和值%3D
+查询字符串中的空格(旧格式)%2B

非保留字符

这些字符在URL的任何部分都不需要编码:

  • 字母: A-Za-z
  • 数字: 0-9
  • 连字符: -
  • 句点: .
  • 下划线: _
  • 波浪号: ~

空格的编码:%20 vs +

空格的编码是URL编码中最容易混淆的部分之一:

  • %20: 空格字符的正确百分号编码,用于路径段
  • +: 空格的替代编码,但只在查询字符串中有效(来自application/x-www-form-urlencoded格式)
路径:  https://example.com/my%20documents/file%20name.pdf  (正确)
路径:  https://example.com/my+documents/file+name.pdf      (错误 - +是字面量)

查询: https://example.com/search?q=hello+world              (正确)
查询: https://example.com/search?q=hello%20world            (也正确)

最佳实践: 在路径段中使用%20,在查询字符串中+%20均可。不确定时,%20始终安全。

各编程语言中的URL编码

JavaScript

JavaScript提供了几个URL编码函数,各有不同的作用范围:

// encodeURIComponent - 编码URI组件(查询参数值)
encodeURIComponent('你好 世界 & 再见')
// 结果: "%E4%BD%A0%E5%A5%BD%20%E4%B8%96%E7%95%8C%20%26%20%E5%86%8D%E8%A7%81"

// encodeURI - 编码完整URI(保留URL结构字符)
encodeURI('https://example.com/path with spaces?q=hello world')
// 结果: "https://example.com/path%20with%20spaces?q=hello%20world"

// decodeURIComponent - 解码URI组件
decodeURIComponent('hello%20world%20%26%20goodbye')
// 结果: "hello world & goodbye"

encodeURIencodeURIComponent的关键区别:

函数不编码的字符使用场景
encodeURI:, /, ?, #, &, =, @, +编码完整URL
encodeURIComponent仅非保留字符编码查询参数值

URLSearchParams API

现代JavaScript提供URLSearchParams处理查询字符串:

// 创建查询字符串
const params = new URLSearchParams();
params.set('name', '张三');
params.set('city', '北京');
params.set('interests', '编程 & 设计');
console.log(params.toString());

// 解析查询字符串
const url = new URL('https://example.com/search?q=hello+world&page=2');
console.log(url.searchParams.get('q'));   // "hello world"
console.log(url.searchParams.get('page')); // "2"

Python

from urllib.parse import quote, unquote, urlencode, parse_qs

# 对用于URL路径的字符串进行编码
quote('你好 世界/路径')  # '%E4%BD%A0%E5%A5%BD%20%E4%B8%96%E7%95%8C/%E8%B7%AF%E5%BE%84'

# 解码百分号编码字符串
unquote('%E4%BD%A0%E5%A5%BD')  # '你好'

# 构建查询字符串
params = {'q': '你好世界', 'category': '图书'}
urlencode(params)  # 'q=%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C&category=%E5%9B%BE%E4%B9%A6'

Java

import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

// 编码
String encoded = URLEncoder.encode("你好世界 & 更多", StandardCharsets.UTF_8);

// 解码
String decoded = URLDecoder.decode(encoded, StandardCharsets.UTF_8);
// 结果: "你好世界 & 更多"

URL中的UTF-8与国际字符

IRI标准

国际化资源标识符(IRI,RFC 3987定义)扩展了URL以支持Unicode字符。但在网络传输时,IRI会使用UTF-8百分号编码转换为URI。

IRI:  https://example.com/北京
URI:  https://example.com/%E5%8C%97%E4%BA%AC

IRI:  https://example.com/search?q=中文搜索
URI:  https://example.com/search?q=%E4%B8%AD%E6%96%87%E6%90%9C%E7%B4%A2

国际化域名(IDN)

包含非ASCII字符的域名使用Punycode编码:

Unicode:  https://中文.com
Punycode: https://xn--fiq228c.com

浏览器如何处理非ASCII URL

现代浏览器在地址栏中显示IRI(Unicode版本)以提高可读性,但通过网络发送的是百分号编码的URI。

常见URL编码问题与解决方案

问题1:重复编码

重复编码发生在已编码的URL被再次编码时:

原文:    hello world
第一次编码: hello%20world
重复编码:  hello%2520world  (%25是%的编码)

解决方案: 在编码前检查输入是否已经编码。

function safeEncodeURIComponent(str) {
  try {
    const decoded = decodeURIComponent(str);
    if (decoded !== str) {
      return str; // 已经编码过了
    }
  } catch (e) {
    // 解码失败,说明有无效编码,重新编码
  }
  return encodeURIComponent(str);
}

问题2:对整个URL进行编码

// 错误:对整个URL编码
const url = 'https://api.example.com/search?q=hello world';
const encoded = encodeURIComponent(url);
// "https%3A%2F%2Fapi.example.com%2Fsearch%3Fq%3Dhello%20world"
// 这作为URL完全是错误的!

// 正确:只编码需要编码的部分
const baseUrl = 'https://api.example.com/search';
const query = encodeURIComponent('hello world');
const correctUrl = `${baseUrl}?q=${query}`;
// "https://api.example.com/search?q=hello%20world"

问题3:API参数中未对特殊字符编码

// Bug: 值中的&破坏了查询字符串
const apiUrl = `https://api.example.com/search?q=Tom & Jerry&page=1`;
// 这会创建三个参数: q=Tom、Jerry、page=1

// 修复: 对参数值进行编码
const apiUrl = `https://api.example.com/search?q=${encodeURIComponent('Tom & Jerry')}&page=1`;
// 正确: q=Tom%20%26%20Jerry&page=1

URL编码参考表

以下是常见编码字符的综合参考:

字符十进制十六进制编码描述
(空格)3220%20空格字符
!3321%21感叹号
"3422%22双引号
#3523%23井号 / 片段分隔符
$3624%24美元符号
%3725%25百分号(转义字符)
&3826%26&符号 / 查询分隔符
/472F%2F斜杠 / 路径分隔符
:583A%3A冒号
=613D%3D等号
?633F%3F问号 / 查询分隔符
@6440%40@符号

总结

URL编码是Web开发中的基础概念,影响到所有处理URL的应用程序。理解百分号编码的工作原理、何时使用encodeURIComponentencodeURI,以及不同编程语言如何处理URL编码,将帮助你避免微妙的bug和安全问题。

关键要点:

  1. JavaScript中值用encodeURIComponent,完整URL用encodeURI
  2. 空格可以是%20+%20始终安全
  3. 非ASCII字符先用UTF-8转换再进行百分号编码
  4. 注意避免重复编码 — 这是最常见的URL编码错误
  5. JavaScript中使用**URLSearchParams**安全构建查询字符串
  6. 在URL中包含用户输入前必须进行编码以防止注入攻击

快速编码解码URL,请收藏我们的URL编码/解码工具

相关资源

常见问题

D

关于作者

Daniel Park

Senior frontend engineer based in Seoul. Seven years of experience building web applications at Korean SaaS companies, with a focus on developer tooling, web performance, and privacy-first architecture. Open-source contributor to the JavaScript ecosystem and founder of ToolPal.

了解更多

分享文章

XLinkedIn

相关文章