URL 编解码:整段、参数值与 %20 的区别
整段编码用 encodeURIComponent 的规则,适合一个参数值;「只编码参数值」会按 ? 和 & 拆开,只处理每个值,保留链接结构。解码则把 %XX 序列还原成原文。
什么时候真的需要
链接里带中文、空格或 & 这类分隔符:直接拼进 URL 会被截断或解析错,必须先编码。参数值里本来就有 %26 时,「只编码参数值」会先解码再编码,不会叠加成 %2526。
从日志、埋点或邮件里拿到 %E4%B8%AD%E6%96%87 这样的串,需要还原成人能读的文本;emoji 这种 4 字节 UTF-8 序列也能正确还原。
对接第三方回调:对方要求 return_url 必须编码后放进另一个参数,这时整段编码和只编码参数值是两种不同结果,选错就会多一层或漏一层。
- 中文、空格参数
- 还原日志里的编码串
- 回调地址嵌套编码
- 核对签名前的规范化字符串
怎么做才不出错
先分清两个函数。encodeURIComponent 会转义 / ? & = 等分隔符,适合单个参数值;encodeURI 保留它们,适合整条链接。本工具的「整段」用的是前者,所以会把 :// 也变成 %3A%2F%2F,要保留 URL 结构就别用整段模式。
「只编码参数值」按 ? 和 & 拆分,逐个处理值,并先解码已有的百分号编码再重新编码,避免 %2526 这种叠加。它不管 # 片段和 ; 分隔,URL 里有这两者时要自己分段。
空格是 %20,不是 +。encodeURIComponent 按 RFC 3986 处理,空格一律写成 %20;把空格写成 + 的是 HTML 表单那套 application/x-www-form-urlencoded 规则。查询串里多数框架两种都收,但签名算法、OAuth、部分老网关会把 + 当成字面的加号。需要 + 时用 URLSearchParams 生成,别手工替换字符,否则会把已经正确的 %2B 也弄坏。
解码报「含有非法的百分号转义」时,通常是孤立的 %、%ZZ,或者 %E4 这种被截断的序列。常见原因:链接被二次编码、被聊天软件按字数截断、原文里本来就有 100% 这种写法。字面的百分号应写成 %25。工具遇到非法序列会整体失败,不会给半截结果。
解一次还是乱码,往往说明原文被编码了两次,常见于回调地址被塞进另一个跳转参数。每次解码只剥一层:%25E4%25B8%25AD 变成 %E4%B8%AD,再变成「中」。连点可以,但要知道自己在剥第几层;更该做的是在源头保证只编码一次。
- 单个值用 encodeURIComponent,整条链接用 encodeURI
- 只编码参数值可避免 %2526 叠加
- 空格是 %20,+ 是表单规则
- 非法 % 序列整体报错,先检查百分号
替代方案与局限
写代码时用 URL 和 URLSearchParams:它们按规范处理编码、+ 和排序,比自己拼字符串可靠。new URL(...).searchParams.set(...) 会自动编码值。
整条 URL 要保留结构就用 encodeURI;要构造表单体或待签名字符串,用 URLSearchParams 的 toString(),它按表单规则输出 +。
本工具的限制:只按 ? 和 & 拆分,不处理 # 片段和 ;;空格输出 %20 而非 +;非法百分号序列直接报错,没有「尽力解码」;也不做 URL 规范化(大小写、默认端口、路径 ..)。
- 代码里用 URL 和 URLSearchParams
- 整条链接 → encodeURI
- 表单、签名 → URLSearchParams
- 需要规范化 → 专门库
常见问题
URL 编码里空格为什么是 %20 不是 +?
因为 encodeURIComponent 按 RFC 3986 处理,空格一律写成 %20。把空格写成 + 的是 HTML 表单那套 application/x-www-form-urlencoded 规则。多数查询串解析器两种都收,但签名、OAuth、部分老网关会把 + 当成字面的加号,算出不同的值。需要 + 时用 URLSearchParams 生成,别手工替换字符,那样会把已经正确的 %2B 一起弄坏。
encodeURI 和 encodeURIComponent 有什么区别?
encodeURIComponent 会转义构成 URL 结构的保留字符,包括 / ? & = : 和 #,所以适合单个参数值;encodeURI 保留这些字符,只编码 URL 里不能直接出现的字符,所以适合整条链接。本工具的整段模式和 encodeURIComponent 一样,会把 :// 变成 %3A%2F%2F。
解码一次还是乱码,是不是要点两次?
多数情况下说明原文被编码了两次。每次解码只剥一层:%25E4%25B8%25AD 变成 %E4%B8%AD,再点一次才变成「中」。回调地址被塞进另一个跳转参数是常见原因。连点两次能得到结果,但更该在源头改成只编码一次,因为双重编码还会让 + 和 & 的语义变得难以预测。
相关工具:URL 编解码