Dev
URL编码完全理解 - 解决中文乱码和特殊字符问题
API调用中中文乱码、特殊字符报错的原因。encodeURI vs encodeURIComponent的区别及实战解决方法。
Toolypet Team
Development Team
URL编码完全理解
"API发送中文参数后,收到的是乱码。"
发送: ?name=张三
收到: ?name=å¼ ä¸
这个问题的原因是URL编码。正确理解后,再也不会被乱码困扰。
为什么需要编码
URL诞生于1990年代,只允许ASCII字符。
URL中安全的字符
A-Z a-z 0-9 - _ . ~
就这些。
URL中有问题的字符
| 字符 | 问题 |
|---|---|
| 中文 | 不是ASCII |
| 空格 | 被解释为URL分隔符 |
& | 参数分隔符 |
? | 查询字符串开始 |
= | 键值分隔符 |
# | 片段开始 |
/ | 路径分隔符 |
编码做了什么
将有问题的字符转换为%XX格式(十六进制)。
空格 -> %20
& -> %26
张 -> %E5%BC%A0 (UTF-8基准3字节)
JavaScript编码函数
核心区别
const text = "hello world&name=张三";
encodeURI(text);
// "hello%20world&name=%E5%BC%A0%E4%B8%89"
// & 和 = 保持不变(维护URL结构)
encodeURIComponent(text);
// "hello%20world%26name%3D%E5%BC%A0%E4%B8%89"
// & -> %26, = -> %3D(全部编码)
什么时候用什么
| 情况 | 函数 | 原因 |
|---|---|---|
| 查询参数值 | encodeURIComponent | 需要编码&、= |
| 整个URL | encodeURI | 维护URL结构 |
| 路径段 | encodeURIComponent | 需要编码/ |
容易犯错的情况
// 错误:对整个URL使用encodeURIComponent
const url = "https://api.com/search?q=测试";
encodeURIComponent(url);
// "https%3A%2F%2Fapi.com%2Fsearch%3Fq%3D%E6%B5%8B%E8%AF%95"
// 无法作为URL使用!
// 正确:只编码值
const query = "测试";
const url = `https://api.com/search?q=${encodeURIComponent(query)}`;
// "https://api.com/search?q=%E6%B5%8B%E8%AF%95"
URLSearchParams - 现代方法
不要直接编码,使用URLSearchParams。
基本用法
const params = new URLSearchParams({
name: "张三",
city: "北京市朝阳区",
tags: "开发者,前端"
});
params.toString();
// "name=%E5%BC%A0%E4%B8%89&city=%E5%8C%97%E4%BA%AC%E5%B8%82%E6%9C%9D%E9%98%B3%E5%8C%BA&tags=%E5%BC%80%E5%8F%91%E8%80%85%2C%E5%89%8D%E7%AB%AF"
自动编码。没有出错的余地。
与URL对象一起使用
const url = new URL("https://api.com/search");
url.searchParams.set("q", "张三");
url.searchParams.set("page", 1);
url.toString();
// "https://api.com/search?q=%E5%BC%A0%E4%B8%89&page=1"
解析(解码)
const url = new URL("https://api.com/search?name=%E5%BC%A0%E4%B8%89");
url.searchParams.get("name"); // "张三" <- 自动解码!
实战问题解决
问题1:双重编码
// 对已编码的值再次编码
const encoded = "%E5%BC%A0%E4%B8%89";
encodeURIComponent(encoded);
// "%25E5%25BC%25A0%E4%B8%89"
// % -> %25 导致完全乱码
解决方案:编码前检查是否已经编码
function safeEncode(str) {
try {
// 如果已编码,先解码再重新编码
return encodeURIComponent(decodeURIComponent(str));
} catch {
// 解码失败 = 未编码状态
return encodeURIComponent(str);
}
}
问题2:空格的两张面孔
%20 vs +
都是空格,但来源不同。
| 方式 | 使用场景 |
|---|---|
%20 | URL标准(RFC 3986) |
+ | HTML表单(application/x-www-form-urlencoded) |
encodeURIComponent("hello world"); // "hello%20world"
new URLSearchParams({q: "hello world"}).toString(); // "q=hello+world"
服务器都能正确处理。但为了一致性,请选择一种方式。
问题3:框架已经编码了
axios、fetch、React Router等自动编码。
// axios - 自动编码
axios.get('/search', { params: { name: '张三' } });
// 请求: /search?name=%E5%BC%A0%E4%B8%89
// 错误:手动编码导致双重编码
axios.get('/search', { params: { name: encodeURIComponent('张三') } });
// 请求: /search?name=%25E5%25BC%25A0... (乱码)
规则:使用框架时,不要手动编码。
服务器端处理
Node.js / Express
// 自动解码
app.get('/search', (req, res) => {
const name = req.query.name; // "张三"
});
// 路径参数也一样
app.get('/users/:name', (req, res) => {
const name = req.params.name; // "张三"
});
Python / Flask
from flask import request
@app.route('/search')
def search():
name = request.args.get('name') # "张三"
PHP
$name = $_GET['name']; // "张三"
// PHP也自动解码
特殊情况
Base64 in URL
标准Base64包含+、/、=,在URL中会有问题。
// 标准Base64
btoa("hello"); // "aGVsbG8="
// URL-safe Base64
function base64UrlEncode(str) {
return btoa(str)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, ''); // 移除填充
}
base64UrlEncode("hello"); // "aGVsbG8"
JWT使用这种格式。
Fragment (#) 注意事项
https://example.com/page?name=张三#section
↑
从这里开始不发送到服务器
#之后(片段)只在浏览器中处理,不发送到服务器。
调试技巧
浏览器地址栏
浏览器为了可读性会显示解码后的内容。
显示: https://example.com/users/张三
实际: https://example.com/users/%E5%BC%A0%E4%B8%89
在开发者工具的Network标签页中查看实际请求URL。
用curl测试
# 直接使用编码后的URL
curl "https://api.com/search?name=%E5%BC%A0%E4%B8%89"
# 让curl来编码
curl -G "https://api.com/search" --data-urlencode "name=张三"
总结
| 情况 | 解决方案 |
|---|---|
| 创建查询参数 | 使用URLSearchParams |
| 只编码值 | encodeURIComponent |
| 编码整个URL | encodeURI |
| 使用框架中 | 不要手动编码 |
| 乱码 | 怀疑双重编码 |
核心原则:尽可能让URLSearchParams或框架来处理,避免手动编码。
相关工具
| 工具 | 用途 |
|---|---|
| URL Encoder | 编码/解码 |
| URL Parser | URL结构分析 |
| Base64 | Base64转换 |
URLencodingdecodingWeb开发API查询字符串
关于作者
Toolypet Team
Development Team
The Toolypet Team creates free, privacy-focused web tools for developers and designers. All tools run entirely in your browser with no data sent to servers.
Web DevelopmentCSS ToolsDeveloper ToolsSEOSecurity