url编码与解码

unimof 2021年03月04日 342次浏览

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程序包即可。