Toolypet
返回博客
Dev

URL编码完全理解 - 解决中文乱码和特殊字符问题

API调用中中文乱码、特殊字符报错的原因。encodeURI vs encodeURIComponent的区别及实战解决方法。

Toolypet Team

Toolypet Team

Development Team

3 分钟阅读

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需要编码&=
整个URLencodeURI维护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  +

都是空格,但来源不同。

方式使用场景
%20URL标准(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
编码整个URLencodeURI
使用框架中不要手动编码
乱码怀疑双重编码

核心原则:尽可能让URLSearchParams或框架来处理,避免手动编码。


相关工具

工具用途
URL Encoder编码/解码
URL ParserURL结构分析
Base64Base64转换
URLencodingdecodingWeb开发API查询字符串

关于作者

Toolypet Team

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