URL 编码,也称为百分号编码,是一种基础机制,使 Web 能够处理 URL 中的各种字符和特殊符号。没有它,我们所知的现代 Web 将无法正常运行。本文探讨 URL 编码和解码的原因、方法和时机。

📋 目录

关键要点

实践 描述
编码保留字符 当保留字符(如 &?/)出现在数据值中时,请务必对其进行编码,以防止它们被解释为 URL 分隔符。
对数据使用 encodeURIComponent 在编码 URL 参数或路径段时,请使用 encodeURIComponent 以确保所有特殊字符都得到正确处理。
对完整 URL 使用 encodeURI 如果需要编码完整的 URL,请使用 encodeURI,它会避免对协议和主机信息进行编码。
服务器端解码 Web 框架(例如 Express、Django)通常会自动解码 URL 参数,但请务必了解上下文,以防止出现 XSS 等安全风险。
不用于安全 URL 编码用于数据完整性,而非安全性。它不会加密或隐藏敏感信息。

什么是 URL 编码以及为什么我们需要它?

URL 编码将字符转换为可以通过互联网安全传输的格式。它将不安全的 ASCII 字符替换为 "%" 后跟两个十六进制数字,表示字符的 ASCII 代码。

URL 编码的需求源于:

  • URL 只能包含 ASCII 字符集中的有限字符
  • 特殊字符如空格、与符号(&)和问号(?)在 URL 中有特殊含义
  • 非 ASCII 字符(如中文、阿拉伯文或表情符号)需要以普遍可理解的格式表示

URL 编码过程:深入解析

保留字符及其编码

某些字符是"保留的",必须在特定上下文中进行编码:

// 常见保留字符及其编码等效形式
const reservedChars = {
  ' ': '%20',    // 空格
  '!': '%21',    // 感叹号
  '#': '%23',    // 井号
  '$': '%24',    // 美元符号
  '%': '%25',    // 百分号
  '&': '%26',    // 与符号
  "'": '%27',    // 单引号
  '(': '%28',    // 左括号
  ')': '%29',    // 右括号
  '*': '%2A',    // 星号
  '+': '%2B',    // 加号
  ',': '%2C',    // 逗号
  '/': '%2F',    // 正斜杠
  ':': '%3A',    // 冒号
  ';': '%3B',    // 分号
  '=': '%3D',    // 等号
  '?': '%3F',    // 问号
  '@': '%40',    // at 符号
  '[': '%5B',    // 左方括号
  ']': '%5D',    // 右方括号
};

实际编码示例

让我们看看不同的字符串如何被编码:

// 原始:"Hello World!"
// 编码后:"Hello%20World%21"

// 原始:"price=$100&discount=20%"
// 编码后:"price%3D%24100%26discount%3D20%25"

// 原始:"search?q=café & books"
// 编码后:"search%3Fq%3Dcaf%C3%A9%20%26%20books"

URL 编码的实际应用

1. REST API 中的查询参数

URL 编码对于在 API 请求中传递参数至关重要:

// 构建搜索 API 请求
const searchTerm = "typescript & react";
const encodedTerm = encodeURIComponent(searchTerm);
// 结果:"typescript%20%26%20react"

const apiUrl = `https://api.example.com/search?q=${encodedTerm}&limit=10`;
// 最终 URL:https://api.example.com/search?q=typescript%20%26%20react&limit=10

2. 表单数据提交

当使用 GET 方法提交表单时,所有表单数据都会在查询字符串中进行 URL 编码:

<form action="/search" method="GET">
  <input type="text" name="q" value="web development">
  <input type="number" name="page" value="1">
  <input type="submit" value="Search">
</form>

<!-- 提交后,URL 变为: -->
<!-- /search?q=web%20development&page=1 -->

3. 包含特殊字符的文件下载

文件名中包含空格或特殊字符的文件需要正确编码:

const fileName = "Quarterly Report Q1 2024.pdf";
const encodedFileName = encodeURIComponent(fileName);
// 结果:"Quarterly%20Report%20Q1%202024.pdf"

const downloadLink = `/download/${encodedFileName}`;

URL 解码:反向过程

URL 解码将百分号编码的字符串转换回其原始形式:

// 编码:"Hello%20World%21"
// 解码:"Hello World!"

// 编码:"price%3D%24100%26discount%3D20%25"
// 解码:"price=$100&discount=20%"

JavaScript 编码/解码方法

现代 JavaScript 提供了内置的 URL 编码和解码方法:

// encodeURIComponent - 编码除以下字符外的所有内容:A-Z a-z 0-9 - _ . ! ~ * ' ( )
const encoded = encodeURIComponent("hello world!"); // "hello%20world%21"

// decodeURIComponent - 解码编码的字符串
const decoded = decodeURIComponent("hello%20world%21"); // "hello world!"

// encodeURI - 编码完整 URL(不编码 :/?&=+)
const urlEncoded = encodeURI("https://example.com/search?q=hello world");
// "https://example.com/search?q=hello%20world"

// decodeURI - 解码完整 URL
const urlDecoded = decodeURI("https://example.com/search?q=hello%20world");
// "https://example.com/search?q=hello world"

常见陷阱和最佳实践

1. 双重编码

避免对已经编码的字符串进行再次编码:

// 错误:双重编码
const term = "hello world";
const wrong = encodeURIComponent(encodeURIComponent(term)); // "hello%2520world"

// 正确:单次编码
const right = encodeURIComponent(term); // "hello%20world"

2. 编码完整 URL 与组件

对完整 URL 使用 encodeURI,对 URL 组件使用 encodeURIComponent

// 对于查询参数
const param = "search query";
const encodedParam = encodeURIComponent(param); // 正确

// 对于完整 URL
const url = "https://example.com/search?q=hello world";
const encodedUrl = encodeURI(url); // 正确

3. 处理非 ASCII 字符

URL 编码正确处理 Unicode 字符:

// 中文字符
encodeURIComponent("中文"); // "%E4%B8%AD%E6%96%87"

// 表情符号
encodeURIComponent("🚀"); // "%F0%9F%9A%80"

// 阿拉伯文本
encodeURIComponent("مرحبا"); // "%D9%85%D8%B1%D8%AD%D8%A8%D8%A7"

安全考虑

虽然 URL 编码有助于数据传输,但它不是安全措施:

  • 不是加密:URL 编码不保护敏感数据
  • SQL 注入:编码的参数仍可能包含恶意负载
  • XSS 攻击:始终在服务器端验证和清理解码的数据

现代 Web 开发与 URL 编码

框架支持

大多数现代 Web 框架自动处理 URL 编码:

React Router:

// React Router 自动处理链接中的编码
<Link to={`/search?q=${searchTerm}`}>搜索</Link>

Express.js:

// Express 自动解码 URL 参数
app.get('/search', (req, res) => {
  const query = req.query.q; // 已解码
  // 处理搜索查询
});

Vue Router:

// Vue Router 处理导航中的编码
this.$router.push({ path: '/search', query: { q: searchTerm } });

结论

URL 编码是一项不可或缺的技术,使现代 Web 成为可能。它确保各种字符和特殊符号可以通过互联网安全传输,从而支持健壮的 Web 应用程序、REST API 和国际内容。

了解何时以及如何使用 URL 编码对每个 Web 开发人员都至关重要。无论您是构建 API 端点、处理表单提交还是处理国际内容,正确的 URL 编码实践将确保您的应用程序在不同的浏览器和平台上可靠工作。

准备好使用 URL 编码了吗?我们的在线工具提供了一种简单高效的方式来编码和解码您的 URL 和参数。

立即尝试 URL 编码/解码工具