12、URL 编解码

一、为什么要 URL 编码


  • 在因特网上传送 URL只能采用 ASCII 字符集
  • 1、只有字母数字 [0-9a-zA-Z]、一些特殊符号 $-_.+!*'() [不包括双引号]、以及某些保留字(空格转换为+),才可以不经过编码直接用于 URL
  • 2、如果 URL 中有汉字,就必须编码后使用。 但是麻烦的是标准的国际组织并没有规定具体的编码方法,而是交给应用程序(浏览器)自己决定。 这导致"URL编码"成为了一个混乱的领域。
  • 3、对于同一个中文,不同的浏览器可能会有不同的编码方式,不要将编码交给浏览器。应该用 JS 在前端对 URL 编码,这样就实现了统一。
    • 如果 key=value 这种传参方式中,value 中包含 ?``=& 等符号,url 的解析会变得很困难。

二、什么是 URL 编码


  • 1、URL 编码通常也被称为百分号编码(percent-encoding),是因为它的编码方式非常简单:
    • 1、使用 % 加上两位的字符——0123456789ABCDEF——代表一个字节的十六进制形式。
    • 2、URL 编码要做的,就是将每一个非安全的 ASCII 字符都被替换为“%xx”格式,
  • 2、对于 非 ASCII 字符,的 URL 编码实现,RFC 文档建议:
    • 1、使用 utf-8 对其进行编码得到相应的字节
      • 如:"中文"使用 UTF-8 编码 得到的字节为 0xE4 0xB8 0xAD 0xE6 0x96 0x87。
    • 2、然后,对每个字节执行百分号编码
      • 如:0xE4 0xB8 0xAD 0xE6 0x96 0x87 经过 Url 编码后得到 “%E4%B8%AD%E6%96%87”。

三、JS 的三种 URL 编码


  • 1、escape
  • 2、encodeURI 函数 (推荐使用)
    • 1、对需要编码的参数用 encodeURI 函数最推荐
    • 2、对应的解码函数是 decodeURI()
  • 3、encodeURIComponent函数(最推荐使用
    • 1、对需要编码的参数用 encodeURIComponent 函数最推荐
    • 2、对应的解码函数是 decodeURIComponent()

四、Java 中的 URL 编码、解码 – URLDecoder 与 URLEncoder


  • URLEncoder:可以把非西欧文字 “张三zxw” 编码成 “%E5%BC%A0%E4%B8%89zxw” 的形式。
    • –在有些场景,无法传输和存储“非西欧文字”,此时就需要用到 URLEncoder 转换。
      • 典型的像 Cookie,Cookie 的值不能使中文的。
  • URLDecoder:可以把 “%E5%BC%A0%E4%B8%89zxw” 的形式解码成 “张三zxw”。
  • URLEncoder 的核心逻辑是:
    • 每个字节视为无符号的 8 位整数(0-255),然后转为 %XX 格式的十六进制字符串。
  • 具体步骤:
    • 将 byte 转换为 int,并屏蔽符号位(通过 & 0xFF)。
    • 将结果转为两位十六进制字符串。如:0xE4 → %E4。
package org.rainlotus.materials.javabase.a01_unicode;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

/**
 * URL 编码解码
 * @author zhangxw
 * @since 0.0.1
 */
public class URLDecoderTest {
	public static void main(String[] args) throws UnsupportedEncodingException {
		String str = "张兴旺zxw";

		// URLDecoder:URL 解码。
		String encodeStr = URLEncoder.encode(str, "GBK");

		// %D5%C5%D0%CB%CD%FAzxw
		System.out.println(encodeStr);

		// URLDecoder:URL 解码。
		// 张兴旺zxw
		System.out.println(URLDecoder.decode(encodeStr, "GBK"));


	// URLEncoder.encode 的原理:
		// 第 1 步:获取字符串 对应编码的 byte 数组。
		byte[] bytes = str.getBytes("GBK");

		// GBK 编码结果:"张兴旺zxw" → 字节数组:[-43, -59, -48, -53, -51, -6, 122, 120, 119]
		System.out.println(Arrays.toString(bytes));

		StringBuilder hexBuilder = new StringBuilder();
		// 第 2 步:将 字节数组:[-43, -59, -48, -53, -51, -6, 122, 120, 119] 中的每个 byte 数字,
			// 转为 【无符号的十六进制】字符串。
		for (byte b : bytes) {
			// 消除符号位影响
			int value = b & 0xFF;
			hexBuilder.append(String.format("%02X ", value));
		}
		// 无符号十六进制: D5 C5 D0 CB CD FA 7A 78 77
		System.out.println("无符号十六进制: " + hexBuilder);

	}
}

五、什么是 application/x-www-form-urlencoded


  • 1、是一种编码类型
    • URL 地址里包含 非西欧字符 的字符串时,
      • 系统会将这些字符转换成 application/x-www-form-urlencoded 字符串。
    • 表单提交中的表单里包含 非西欧字符 的字符串时,
      • 系统也会将这些字符转换成 application/x-www-form-urlencoded 字符串,
      • 然后,在服务器端自动解码
    • FORM 元素的 enctype 属性指定了表单数据向服务器提交时所采用的编码类型
      • 默认的缺省值是 application/x-www-form-urlencoded
  • 2、在向服务器发送大量的文本、包含大量非 ASCII 字符的文本或二进制数据时这种编码方式效率很低
    • 这时,就要使用另一种编码类型multipart/form-data”。
      • 如:做文件上传时,表单的 enctype 属性一般会设置成“multipart/form-data”。
    • Browser 端 表单的 ENCTYPE 属性值为 multipart/form-data
      • 它告诉我们传输的数据要用到多媒体传输协议,由于多媒体传输的都是大量的数据
      • 所以,规定上传文件必须是 post 方法,<input> 的 type 属性必须是 file
<think>好的,用户想了解如何实现URL解码,并需要示例代码。首先,我需要回忆URL解码的基本概念和作用。URL解码主要是将编码过的URL字符串转换回原始格式,比如把"%20"变回空格。接下来,我应该考虑不同编程语言的实现方法,因为用户提供的引用里提到了PHP、Java、C语言等,可能用户希望看到多种语言的示例。 首先,确定用户可能使用的语言。用户没有明确指定,所以最好覆盖常见的几种,比如PHP、Java、Python、JavaScript和C语言。这样能够满足不同开发者的需求。然后,根据引用中的资料,PHP使用urldecode函数,JavaURLDecoder类,Python有urllib.parse模块,JavaScript有decodeURIComponent函数,而C语言需要手动处理或者用库函数。 接下来,每个示例需要简洁明了,展示解码前后的对比。比如PHP中的代码示例,用户提供的引用里有编码的例子,解码应该类似。需要注意特殊字符的处理,比如空格变成%20,中文或其他多字节字符的编码问题。同时,要提到不同语言中可能存在的差异,比如JavaScript中的两种解码函数区别。 另外,用户可能关心为什么需要URL编解码,引用[4]提到是因为特殊字符和多字节编码的问题,需要在回答中简要说明。还要注意提醒用户注意不同语言对空格的编码差异,比如+和%20,确保解码时正确处理。 最后,检查示例代码的正确性,确保没有语法错误,并说明运行结果。例如Java示例中的URLDecoder.decode方法需要指定编码格式,如UTF-8,避免乱码。Python 3的示例要区分版本,因为urllib在Python 2和3中有变化,用户可能容易混淆,所以需要明确说明。 总结步骤:解释URL解码的作用,列举各语言示例,注意事项,以及可能的问题点。确保回答结构清晰,覆盖主要语言,并引用提供的资料作为参考。</think>### URL解码实现方法与示例代码 URL解码是将经过百分比编码(如`%20`表示空格)的字符串还原为原始字符的过程,常用于处理表单提交、API参数传递等场景[^4]。 #### 一、各语言实现方法 1. **PHP** ```php <?php $encoded = "https%3A%%2F%2Fwww.example.com%2F%3Fname%3DJohn%20Doe%26age%3D25"; $decoded = urldecode($encoded); echo "Decoded URL: " . $decoded; // 输出:https://www.example.com/?name=John Doe&age=25 ?> ``` *特点*:`urldecode()`函数自动处理`+`和`%20`均转为空格[^1]。 2. **Java** ```java import java.net.URLDecoder; public class Main { public static void main(String[] args) throws Exception { String encoded = "https%3A%2F%2Fwww.example.com%2F%E4%BD%A0%E5%A5%BD"; String decoded = URLDecoder.decode(encoded, "UTF-8"); System.out.println("Decoded URL: " + decoded); // 输出:https://www.example.com/你好 } } ``` *注意*:必须显式指定字符编码(如UTF-8)[^2][^3]。 3. **Python** ```python from urllib.parse import unquote encoded = "https%3A%2F%2Fwww.example.com%2F%3Fq%3D%E6%B5%8B%E8%AF%95" decoded = unquote(encoded) print(f"Decoded URL: {decoded}") # 输出:https://www.example.com/?q=测试 ``` *Python 3特有*:`unquote()`支持嵌套解码。 4. **JavaScript** ```javascript const encoded = "https%3A%2F%2Fwww.example.com%2F%3Fcity%3D%E5%8C%97%E4%BA%AC"; const decoded = decodeURIComponent(encoded); console.log(decoded); // 输出:https://www.example.com/?city=北京 ``` *对比*:`decodeURI()`不解码`#`等保留字符,而`decodeURIComponent()`解码全部字符。 5. **C语言** ```c #include <stdio.h> #include <stdlib.h> char* url_decode(const char* src) { char* decoded = malloc(strlen(src) + 1); char* p = decoded; while (*src) { if (*src == '%' && isxdigit(*(src+1)) && isxdigit(*(src+2))) { *p++ = strtol(src+1, NULL, 16); src += 3; } else { *p++ = *src++; } } *p = '\0'; return decoded; } int main() { char* decoded = url_decode("https%3A%2F%2Fwww.example.com%2F"); printf("%s", decoded); // 输出:https://www.example.com/ free(decoded); return 0; } ``` *注意*:需手动处理内存分配和释放。 #### 二、关键注意事项 1. **编码一致性**:编解码必须使用相同字符集(如UTF-8) 2. **空格处理**:`+`和`%20`在不同语言中的默认行为不同 3. **多次解码**:避免对已解码字符串重复操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值