url是网络世界的基石,在前后端编码中,经常碰到需要对url进行编解码的情况,本文整理了 url 编解码的,需要的请拿好。
1. 了解 url 编码
URL编码通常也被称为百分号编码(percent-encoding),也就是我们经常在域名后面看到那串带百分号的奇怪字符:
https://codercouch.com/archives/you-get%E9%98%85%E7%89%87%E4%BA%BA%E7%9A%84%E7%A6%8F%E5%88%A9%E7%9C%8B%E5%88%B0%E8%87%AA%E5%B7%B1%E5%96%9C%E6%AC%A2%E7%9A%84%E5%B0%B1%E7%94%A8%E5%AE%83%E4%B8%8B%E8%BD%BD%E5%90%A7
那么问题来了,我们为什么需要对 url 进行编解码呢?直接传输不香吗?
URL 是资源在网络上的唯一标识,和人的身份证差不多一个意思,如果你不按照URL规范来玩,那么其他人就访问不了你的资源。
如果英文还 OK 的话,移步 RFC1738 详细阅读。
2. 编码方法
如果 url 包含规范定义字符集之外的字符,就需要进行转码,对于非ASCII字符,RFC文档建议使用utf-8对其进行编码得到相应的字节,然后对每个字节执行百分号编码。
2.1 Javascript
- encodeURI/decodeURI
它着眼于对整个URL进行编码,因此除了常见的符号以外,对其他一些在网址中有特殊含义的符号"; / ? : @ & = + $ , #",也不进行编码。编码后,它输出符号的utf-8形式,并且在每个字节前加上%。
**** 需要注意的是,它不对单引号’编码
实例:
var a = 'https//codercouch.com/代码攻城狮+\''; var b = encodeURI(a); var c = decodeURI(b); console.log("编码:" + b); console.log("解码:" + c);
输出:
编码:https//codercouch.com/%E4%BB%A3%E7%A0%81%E6%94%BB%E5%9F%8E%E7%8B%AE++' 解码:https//codercouch.com/代码攻城狮++'
- escape/unescape
对除ASCII字母、数字、标点符号 @ * _ + - . / 以外的其他字符进行编码。
实例:
var a = 'https//codercouch.com/代码攻城狮+\''; var b = escape(a); var c = unescape(b); console.log("编码:" + b); console.log("解码:" + c);
输出:
编码:https//codercouch.com/%u4EE3%u7801%u653B%u57CE%u72EE++%27 解码:https//codercouch.com/代码攻城狮++'
- encodeURIComponent/decodeURIComponent(推荐使用)
它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。因此,"; / ? : @ & = + $ , #",这些在encodeURI()中不被编码的符号,在encodeURIComponent()中统统会被编码
实例:
var a = 'https//codercouch.com/代码攻城狮+\''; var b = encodeURIComponent(a); var c = decodeURIComponent(b); console.log("编码:" + b); console.log("解码:" + c);
输出:
编码:https%2F%2Fcodercouch.com%2F%E4%BB%A3%E7%A0%81%E6%94%BB%E5%9F%8E%E7%8B%AE%2B%2B' 解码:https//codercouch.com/代码攻城狮++'
三种方式加解密同一个url「https//codercouch.com/代码攻城狮+'」对比,我们可以发现, encodeURIComponent/decodeURIComponent 是对整个 url 进行了完成编码,没有遗漏;encodeURI/decodeURI最后的单引号没有编码;escape/unescape则没有对倒数第二个+进行编码。
2.2 Java
public static String getURLEncoderString(String str) {
String result = "";
if (null == str) {
return "";
}
try {
result = java.net.URLEncoder.encode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
public static String URLDecoderString(String str) {
String result = "";
if (null == str) {
return "";
}
try {
result = java.net.URLDecoder.decode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
注意:java.net的url编码方法在对一些特殊符号编码时有个bug,如:+号decord时,+号会变成空格,需要把+号替换成%2B,str=str.replaceAll("\+", "%2B");
2.3 C#
在 ASP.net core 中,提供了一个 WebUtility 类来实现该转换:
namespace System.Net
{
//
// 摘要:
// Provides methods for encoding and decoding URLs when processing Web requests.
public static class WebUtility
{
public static string UrlDecode(string encodedValue);
public static string UrlEncode(string value);
}
}
对于 ASP.NET Core 2.0+, WebUtility 类迁移到 System.Runtime.Extensions nuget程序包,在 ASP.NET Core 项目中默认引用,直接使用即可。
class Program
{
static void Main(string[] args)
{
string rawUri = "https//codercouch.com/代码攻城狮+'";
string encodedUri = WebUtility.UrlEncode(rawUri);
Console.WriteLine($"编码:{encodedUri}");
string decodedUri = WebUtility.UrlDecode(encodedUri);
Console.WriteLine($"解码:{decodedUri}");
Console.WriteLine("按任意键退出...");
Console.ReadKey();
}
}
对于 ASP.NET Core 2.0以前的版本,需要手动添加添加 Microsoft.AspNetCore.WebUtilities nuget程序包即可。