encode & decode 使用指南

encode & decode 使用指南

  • 一、先抛结论
    • 1. 所有 `query` 的拼接,`=` 后的字符串必须 `encode`
    • 2. 所有 `query` 的解析,`= `后的字符串应该 `decode`
  • 二、场景分析
    • 1. `url` 拼接时,没有做 `encode`,`url` 解析时做了 `decode`
    • 2. `url`拼接时,没有做`encode`,`url`解析时也没有做`decode`
    • 3. `url`拼接时,做了 `encode`,`url` 解析时没有做 `decode`
    • 4. `url` 拼接时,做了 `encode`,`url`解析时做了`decode`
    • 特别提醒
  • 三、总结

一、先抛结论

1. 所有 query 的拼接,= 后的字符串必须 encode

  • 函数功能介绍

encodeURI() 函数通过将特定字符的每个实例替换为一个、两个、三或四转义序列来对统一资源标识符 (URI) 进行编码 (该字符的 UTF-8 编码仅为四转义序列)由两个 “代理” 字符组成)。

encodeURIComponent() 函数通过将一个,两个,三个或四个表示字符的UTF-8编码的转义序列替换某些字符的每个实例来编码 URI (对于由两个“代理”字符组成的字符而言,将仅是四个转义序列) 。

  • 测试demo
> var url = "http://localhost:8080/pro?a=1&b=张三&ie=utf-16&c=aaa #index.html";
> var url2 = encodeURI(url)
"http://localhost:8080/pro?a=1&b=张三&ie=utf-16&c=aaa%20#index.html"
> var url3 = encodeURIComponent(url)
"http%3A%2F%2Flocalhost%3A8080%2Fpro%3Fa%3D1%26b%3D%E5%BC%A0%E4%B8%89%26ie%3Dutf-16%26c%3Daaa%20%23index.html"

从上面的例子,可以看出:
encodeURI()编码后的结果是:空格被替换成了%20,除了空格之外的任何字符都没有改变;
encodeURIComponent()则是将所有非字母数字字符替换成对应编码。
encodeURI()可以对整个URI进行使用,而encodeURIComponent()只适用于对附加URI后面的字符串使用。
所以一般来说,我们使用更多的的是encodeURIComponent(),因为我们更需要对查询字符串进行编码,而不是整个URI

  • 具体用法

encodeURI()用于整个url跳转,比如:
转化前: location.href = "http://localhost:8080/pro?a=1&b=张三&ie=utf-16&c=aaa #index.html";
转化后: location.href = "http://localhost:8080/pro?a=1&b=张三&ie=utf-16&c=aaa%20#index.html"
本例中只是将中文转成%...,传过去再解码就可以拿到中文

encodeURIComponent()用于参数的传递,参数包含特殊字符可能会造成间断。比如:
var paramUrl = "http://localhost:8080/aa?a=1&b=2&c=3";
var url = "http://localhost:8080/pp?a=1&b="+ paramUrl;
应该使用encodeURIComponent()进行转码,
结果:http://localhost:8080/pp?a=1&b=http%3A%2F%2Flocalhost%3A8080%2Faa%3Fa%3D1%26b%3D2%23%26c%3D3

2. 所有 query 的解析,=后的字符串应该 decode

  • 函数功能介绍

decodeURI() 函数能解码由encodeURI 创建或其它流程得到的统一资源标识符(URI)。

decodeURIComponent() 方法用于解码由 encodeURIComponent 方法或者其它类似方法编码的部分统一资源标识符(URI)。

  • 测试demo
var uri = 'https://www.baidu.com/s?ie=utf-16&word=hello%20%24#index.html';

decodeURI(uri)      //https://www.baidu.com/s?ie=utf-16&word=hello %24#index.html

decodeURIComponent(uri) //https://www.baidu.com/s?ie=utf-16&word=hello $#index.html

因为uri中有编码值%20%24decodeURI只可以把%20转化为空格,不会对%24仅从任何处理,因为%24表示$符号,$符号不是使用encodeURI替换的。
decodeURIComponent可以解释任何特殊字符的编码。

二、场景分析

// 目标地址
var url = 'https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1&b=张三&ie=utf-16&word=hello #index.html'

1. url 拼接时,没有做 encodeurl 解析时做了 decode

url拼接没做encode,则

  • 第一种情况
>var url = 'https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1&b=张三&ie=utf-16&word=hello #index.html'

url解析时做了decode

>var url1 = decodeURIComponent(url)
"https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1&b=张三&ie=utf-16&word=hello #index.html"

所以,这个是正常跳转

  • 第二种情况,形如
> `https://host1/path1?url=https://host2/path2?key1=val1&key2=val2`
> // 例如
> var url = 'https://www.baidu.com?url=https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1&b=张三&ie=utf-16&word=hello #index.html'

试问 key2=val2host1 链接的参数,还是 host2 链接的参数?具体点

> url
 "https://www.baidu.com?url=https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1&b=张三&ie=utf-16&word=hello #index.html"

>  function getQuery(name, url) { 
...    //参数:变量名,url为空则表从当前页面的url中取
...    var u = arguments[1] || window.location.search, 
...    reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"), 
...    r = u.substr(u.indexOf("\?") + 1).match(reg); 
...    return r !== null ? r[2] : "";
...}

> getQuery("word",url3)
 "hello #index.html"
 
> var getUrl = getQuery("url",url3) 
 "https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1"
 
> decodeURIComponent(getUrl) 
 "https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1"

明显与我们目标地址不符,就出错了

2. url拼接时,没有做encodeurl解析时也没有做decode

url拼接没做encode,则

  • 第一种情况
> var url = 'https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1&b=张三&ie=utf-16&word=hello #index.html'

url解析时没做decode

>var url2 = url
"https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1&b=张三&ie=utf-16&word=hello #index.html"

所以,肯定是正常跳转

  • 第二种情况
> url
 "https://www.baidu.com?url=https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1&b=张三&ie=utf-16&word=hello #index.html"

> getQuery("word",url3)
 "hello #index.html"
 
> var getUrl = getQuery("url",url3) 
 "https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1"
 
> getUrl
 "https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1"

明显与我们目标地址不符,就出错了

3. url拼接时,做了 encodeurl 解析时没有做 decode

url 拼接做了 encode ,则

> var url = 'https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1&b=张三&ie=utf-16&word=hello #index.html'
> var url2 = "https://www.baidu.com"
> var encodeUrl = encodeURIComponent(url)
"https%3A%2F%2Fjf3-shop-test.wanyol.com%2FactivityHtml%2Fsms_redirect.html%3Fa%3D1%26b%3D%E5%BC%A0%E4%B8%89%26ie%3Dutf-16%26word%3Dhello%20%23index.html" // location.href不能正常跳转的
> var url3 = url2 + "?url=" + encodeUrl 
 'https://www.baidu.com?url=https%3A%2F%2Fjf3-shop-test.wanyol.com%2FactivityHtml%2Fsms_redirect.html%3Fa%3D1%26b%3D%E5%BC%A0%E4%B8%89%26ie%3Dutf-16%26word%3Dhello%20%23index.html'

url解析时没做decode

> var getUrl = getQuery("url",url3)  
 "https%3A%2F%2Fjf3-shop-test.wanyol.com%2FactivityHtml%2Fsms_redirect.html%3Fa%3D1%26b%3D%E5%BC%A0%E4%B8%89%26ie%3Dutf-16%26word%3Dhello%20%23index.html" // location.href不能正常跳转的

所以,肯定是不能正常跳转

4. url 拼接时,做了 encodeurl解析时做了decode

url拼接做了encode,则

> var url = 'https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1&b=张三&ie=utf-16&word=hello #index.html'
> var url2 = "https://www.baidu.com"
> var encodeUrl = encodeURIComponent(url)
"https%3A%2F%2Fjf3-shop-test.wanyol.com%2FactivityHtml%2Fsms_redirect.html%3Fa%3D1%26b%3D%E5%BC%A0%E4%B8%89%26ie%3Dutf-16%26word%3Dhello%20%23index.html" // location.href不能正常跳转的
> var url3 = url2 + "?url=" + encodeUrl 
 'https://www.baidu.com?url=https%3A%2F%2Fjf3-shop-test.wanyol.com%2FactivityHtml%2Fsms_redirect.html%3Fa%3D1%26b%3D%E5%BC%A0%E4%B8%89%26ie%3Dutf-16%26word%3Dhello%20%23index.html'

url解析时做了decode

> var getUrl = getQuery("url",url3) 
 "https%3A%2F%2Fjf3-shop-test.wanyol.com%2FactivityHtml%2Fsms_redirect.html%3Fa%3D1%26b%3D%E5%BC%A0%E4%B8%89%26ie%3Dutf-16%26word%3Dhello%20%23index.html"
> var url22 = decodeURIComponent(getUrl)
 "https://jf3-shop-test.wanyol.com/activityHtml/sms_redirect.html?a=1&b=张三&ie=utf-16&word=hello #index.html"

所以,肯定是正常跳转

特别提醒

  • encodeURIComponent 使用2次

从使用上看来,javascript 使用 encodeURIComponent 编码一次,如果是作为 Url 请求发送,浏览器是自动会作一次解码,编码方式为浏览器默认。这样在一次编码后,请求到后台后,比如中文就成为乱码了。中间即使编码方式是一致也会乱码。解决方法是在前台 javascript 使用 encodeURIComponent 两次,这样浏览器解码一次后,还是一种编码后的字符,传递到后台就不会是乱码,当然你得在后台做一次解码工作。

  // 比如你把一个请求:
  > `http://localhost:8080/sxkj/news/actionNewsByCategoryId.do?categoryId=3&categoryName=%E4%BA%BA%E6%89%8D%E6%8B%9B%E8%81%98`
  // 浏览器是自动把我categoryName后面的给解码为了中文“人才招聘”,请求到了后台是乱码,而把categoryName后面“%E4%BA%BA%E6%89%8D%E6%8B%9B%E8%81%98”,再次编码,作为参数请求后台,后台拿到的就是正确的中文字符了。
  > decodeURIComponent('%E4%BA%BA%E6%89%8D%E6%8B%9B%E8%81%98')
  '人才招聘'

三、总结

所以对paramencode很容易出现问题,上面的demo 我们解析之后的getUrl,与我们的目标url,看着差不多,但丢失参数及信息,说明了urlparam必须encode,如果解析的时候,我们不decode,是不能正常实现跳转的 ,所以我们也阔以通过encodedecode验证我们的准确性,encodedecode 规范也显得至关重要了。

你可能感兴趣的:(tools,JS)