← Back to Blog / Tools / URL 编码完全指南

🔗 URL 编码完全指南:百分号编码原理、encodeURI vs encodeURIComponent 详解

2026-07-06 · 约 10 分钟

你有没有在浏览器地址栏里见过这样的东西:https://example.com/search?q=%E4%B8%AD%E5%9B%BD?那个 %E4%B8%AD%E5%9B%BD 就是「中国」两个字的 URL 编码形式。

URL 编码(也叫「百分号编码」/ Percent Encoding)是 Web 开发中最基础也最容易踩坑的知识点之一。这篇文章一次给你讲透。

01 为什么需要 URL 编码?

URL 的设计初衷只支持 ASCII 字符集,而且其中很多字符有特殊含义。比如 / 用来分隔路径、? 表示查询参数的开始、# 表示锚点。

如果你想把「中国」或一个空格塞进 URL 里,直接放进去会出问题。URL 编码解决了两个核心问题:

02 编码规则:百分号 + 两位十六进制

规则非常简单:把一个字符的 UTF-8 字节值前面加上 %

举个例子,「中」字的 UTF-8 编码是 E4 B8 AD(三个字节),所以 URL 编码后就是 %E4%B8%AD

字符     UTF-8 字节              URL 编码
------------------------------------------
中       E4 B8 AD               %E4%B8%AD
国       E5 9B BD               %E5%9B%BD
空格     20                     %20
!        21                     %21
~        7E                     %7E

💡 注意空格可以编码为 %20,但在 application/x-www-form-urlencoded 里也可以编码为 +。不过 URL 路径里 + 就是字面加号,不会变成空格——这是很多人踩的坑。

03 保留字符 vs 非保留字符

RFC 3986 把 URL 里的字符分成两类:

非保留字符(不需要编码):

A-Z a-z 0-9 - _ . ~

保留字符(有特殊含义,需要编码):

: / ? # [ ] @ ! $ & ' ( ) * + , ; =

——但这有个微妙的地方:保留字符「在特殊含义的语境下才需要编码」。比如 / 在路径分隔符的位置不需要编码,但如果你要把 / 作为查询参数的值,那就得编码成 %2F

04 encodeURI vs encodeURIComponent:最常踩的坑

JavaScript 提供了两个函数,它们的区别是 面试必考题、开发必踩坑

encodeURI

对整个 URL 编码,保留 URL 语义

encodeURI("https://ex.com/路径?q=你好")
// 结果:
// https://ex.com/%E8%B7%AF%E5%BE%84?q=%E4%BD%A0%E5%A5%BD

// ❌ 不会编码这些:
// : / ? # [ ] @ ! $ & ' ( ) * + , ; =

// 所以 query 参数值里如果有
// & 或 =,会被当成 URL 语法解析
encodeURIComponent

编码查询参数值,编码所有非字母数字

encodeURIComponent("你好&世界")
// 结果:%E4%BD%A0%E5%A5%BD%26%E4%B8%96%E7%95%8C

// ✅ & 被编码为 %26
// ✅ = 被编码为 %3D
// ✅ / 被编码为 %2F

// 适合用于 query 参数值

黄金法则:

⚠️ 很多新手在拼接 URL 时用 encodeURI("https://api.com?name=" + userInput),当 userInput 包含 & 时,参数就断掉了。正确做法是对参数值用 encodeURIComponent 单独编码。

05 各种语言的 URL 编码实现

JavaScript

// 编码整个 URL(保留 URL 结构)
encodeURI("https://example.com/路径")
// → "https://example.com/%E8%B7%AF%E5%BE%84"

// 编码参数值(安全!)
encodeURIComponent("你好&世界=test")
// → "%E4%BD%A0%E5%A5%BD%26%E4%B8%96%E7%95%8C%3Dtest"

// 解码
decodeURI("%E8%B7%AF%E5%BE%84")
// → "路径"
decodeURIComponent("%E4%BD%A0%E5%A5%BD%26")
// → "你好&"

Python

from urllib.parse import quote, unquote, urlencode

# 编码
quote("你好")        # → '%E4%BD%A0%E5%A5%BD'
quote("/", safe="")  # → '%2F'  (safe='' 表示不保留任何字符)

# 解码
unquote('%E4%BD%A0%E5%A5%BD')  # → '你好'

# 构建 query string
urlencode({"q": "你好&世界", "page": 1})
# → 'q=%E4%BD%A0%E5%A5%BD%26%E4%B8%96%E7%95%8C&page=1'

Java

import java.net.URLEncoder;
import java.net.URLDecoder;

// 编码(注意:会把空格变成 +)
URLEncoder.encode("你好", "UTF-8")
// → "%E4%BD%A0%E5%A5%BD"

// 解码
URLDecoder.decode("%E4%BD%A0%E5%A5%BD", "UTF-8")
// → "你好"

💡 Java 的 URLEncoder 会把空格编码为 +(遵循 application/x-www-form-urlencoded 规范),而不是 %20。如果你的后端是 Java/Spring,解码时注意处理 +

PHP

<?php
// 编码
urlencode("你好&世界")
// → "%E4%BD%A0%E5%A5%BD%26%E4%B8%96%E7%95%8C"

rawurlencode("你好&世界")
// → "%E4%BD%A0%E5%A5%BD%26%E4%B8%96%E7%95%8C"

// 区别:urlencode 把空格变成 +,rawurlencode 把空格变成 %20
// 推荐使用 rawurlencode,兼容 RFC 3986

// 解码
urldecode("%E4%BD%A0%E5%A5%BD")
urldecode("%E4%BD%A0%E5%A5%BD")

Go

import "net/url"

// 编码
url.QueryEscape("你好&世界")
// → "%E4%BD%A0%E5%A5%BD%26%E4%B8%96%E7%95%8C"

url.PathEscape("你好")
// → "%E4%BD%A0%E5%A5%BD"

// 解码
url.QueryUnescape("%E4%BD%A0%E5%A5%BD")
// → "你好", nil

06 URL 编码的 5 个常见坑

坑 1:用 encodeURI 拼接参数值

// ❌ 错误
const url = "https://api.com?q=" + encodeURI(userInput)
// 如果 userInput = "hello&world",url 中 q=hello,world 被当成了新参数

// ✅ 正确
const url = "https://api.com?q=" + encodeURIComponent(userInput)

坑 2:对已经编码的字符串再次编码

// 如果 input 已经是 "%E4%BD%A0%E5%A5%BD"
encodeURIComponent(input)
// → "%254%E4%25BD%25A0%E5..."  (% 被转成了 %25)

// ✅ 再次解码后再编码,或者保持原样
decodeURIComponent(input)

坑 3:Java 的 + 号迷思

Java 的 URLEncoder 把空格变成 +,但 JavaScript 的 decodeURIComponent 不认 +。如果你前端 JS 解码 Java 编码的数据,记得先替换 +%20

坑 4:忘了编码 # 和 /

# 在 URL 里是片段标识符(锚点),/ 是路径分隔符。如果你把文件路径或 ID 作为参数传递,一定要用 encodeURIComponent 把它们转掉。

坑 5:不同规范的空格编码

application/x-www-form-urlencoded:  空格 → +
RFC 3986 URL 路径:                  空格 → %20
HTML form GET 提交:                 空格 → +
JSON 中的 URI:                      空格 → %20

07 总结速查表

场景用什么空格编码
拼接 URL 路径段encodeURIComponent / rawurlencode%20
拼接 query 参数值encodeURIComponent / url.QueryEscape%20+
表单提交 (POST form)encodeURIComponent+
对整个 URL 轻微编码encodeURI%20
JavaScript URL 对象浏览器自动处理自动
Python requests 库params 参数自动处理自动

🧰 在线 URL 编解码工具

懒得手动编码?试试在线工具,粘贴即用,支持中英文和特殊字符。

打开 URL 编解码工具 →

08 延伸阅读