为什麼encodeURI/encodeURIComponent()要调用两次来进行转码?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什麼encodeURI/encodeURIComponent()要调用两次来进行转码?相关的知识,希望对你有一定的参考价值。
主要是为了解决乱码问题。.encodeURL函数主要是来对URI来做转码,它默认是采用的UTF-8的编码.
. UTF-8编码的格式:一个汉字来三个字节构成,每一个字节会转换成16进制的编码,同时添加上%号.
假设页面端输入的中文是一个“中”,按照下面步骤进行解码
1.第一次encodeURI,按照utf-8方式获取字节数组变成[-28,-72-83],对字节码数组进行遍历,把每个字节转化成对应的16进制数,这样就变成了[E4,B8,AD],最后变成[%E4,%B8,%AD] 此时已经没有了多字节字符,全部是单字节字符。
2、第二次encodeURI,进行编码,会把%看成一个转义字符,并不编码%以后字符,会把%编码成%25.把数组最后变成[%25E4,%25B8,%25AD]然后就把处理后的数据[%25E4,%25B8,%25AD]发往服务器端,
当应用服务器调用getParameter方法,getParameter方法会去向应用服务器请求参数
应用服务器最初获得的就是发送来的[%25E4,%25B8,%25AD],应用服务器会对这个数据进行URLdecode操作,应用服务器进行解码的这一次,不管是按照UTF-8,还是GBK,还是ISO-8859,,都能得到[%E4,%B8,%AD],因为都会把%25解析成%.并把这个值返回给getParameter方法
3、再用UTF-8解码一次,就得到"中"了。
如果不编码两次,当服务器自动解码的时候,假如是按照ISO-8859去解码UTF-8编码的东西,就会出现乱码。 参考技术A 1.tomcat 中 url 是默认的ISO88591码的(可以在server.xml中设置)
2.tomcat 会自动对提交的url进行 转码 转成设置的编码
综上两个条件,encodeURI一次 会自动被TOMCAT解码成设定的编码.
如果是解码后是中文,而默认的ISO88591不支持 就乱码了.
所以要 encodeURI两次 然后再用java解码一次就可以了.(另一次解码TOMCAT做了)
以上本人亲身经历验证 参考技术B url中传递中文时编码方式是iso8859-1,如果接收时不是相同编码就会出现乱码问题,如果用encodeURI方式转码,接收后再转回来,就不会出现乱码问题。
参考技术C 实例
在本例中,我们将使用 encodeURI() 对 URI 进行编码:
<script type="text/javascript">
document.write(encodeURI("http://www.w3school.com.cn")+ "<br />")
document.write(encodeURI("http://www.w3school.com.cn/My first/"))
document.write(encodeURI(",/?:@&=+$#"))
</script>
输出:
http://www.w3school.com.cn
http://www.w3school.com.cn/My%20first/
,/?:@&=+$#
没看见两次的情况
参考资料:http://www.w3school.com.cn/js/jsref_encodeuri.asp
encodeURI() 為什麼URI要編碼?
encodeURI 可以為URI編碼,使其符合URI規範。
URI是Uniform Resource Identifier 的縮寫,中文翻譯為 "統一資源標誌符" 。
為什麼要對URI編碼,什麼時候用的到URI編碼?
如果對URI編碼很陌生,那我們先來看個例子,看看URI編碼跟我們有多常接觸。
先打開google的網頁:
在搜尋欄輸入"維克的煩惱",按下google搜尋,等結果出來。
老實說我滿期待你看到這個部落格在第一名的位置 XD"。
不過這不是現在的重點。我們把視線移到位址欄。
把它複製下來:
https://www.google.com.tw/#hl=zh-TW&tbo=d&site=&source=hp&q=%E7%B6%AD%E5%85%8B%E7%9A%84%E7%85%A9%E6%83%B1&oq=%E7%B6%AD%E5%85%8B%E7%9A%84%E7%85%A9%E6%83%B1&gs_l=hp.12...36398.36398.0.37530.1.1.0.0.0.0.34.34.1.1.0.pchsnhae..0.0...1c.1.Y1Fa80-ocAE&bav=on.2,or.r_gc.r_pw.&bvm=bv.1355325884,d.dGY&fp=152a56cbfacd4238&bpcl=39967673&biw=1843&bih=887
好長一串。現在來看一下q=後面的那一串紅色編碼。
var str="%E7%B6%AD%E5%85%8B%E7%9A%84%E7%85%A9%E6%83%B1" ;
document.writeln(decodeURI(str));
輸出=>維克的煩惱。
沒錯這串紅色編碼就是對"維克的煩惱"進行encodeURI編碼的結果。所以說encodeURI就藏在生活中..XD"
(事實上對於參數的URI編碼,使用encodeURIComponent()才是正確的,可以避免功能性的字符造成URI的混淆,
不過這裡沒有使用功能性字符,所以其實也沒啥差。)
現在來點耐心,看看個URI簡短介紹吧,好吧!如果還是不習慣URI這名稱的話,其實可以暫時把它想成是網址...
雖然URI不只被用在網址的表現,但是身為一個WEB前端應用程式開發人員...........業餘的..我...
最常接觸到的應該也是網址了吧。
URI短介:
URI可以被當成URL(統一資源定位符)或URN(统一资源名),或是兩個合起來。
URL通常代表著位址,URN則是資源的名字。
絕對URI( absolute URI )的語法如下:
<scheme>:<scheme-specific-part>
不過我們常用的網址是URI的一個子集,一般型URI(generic URI 是這樣翻譯嗎==? 文章尾端有附原文),
語法如下:
<scheme>://<authority><path>?<query>
拿這文章的網址當個例子吧:
http://www.victsao.com/blog/81-javascript/89-javascript-encodeuri-uri
scheme:http
authority:www.victsao.com
path:/blog/81-javascript/89-javascript-encodeuri-uri
query:尷尬了!沒有耶!這啥爛例子。
好吧來看一下RFC3986 附的的例子吧,一次來兩個:
來自:http://tools.ietf.org/html/rfc3986
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
| ____________________|__
/ \ / \
urn:example:animal:ferret:nose
URI編碼:
URI允許的字元包括:大小寫英文字母,數字,標記(mark),保留字跟跳脫編碼。
標記:- _ . ! ~ * ‘ ( )
保留字:; / ? : @ & = + $ ,
跳脫編碼:%加兩個16進位編碼。例:%AB、%FB
注意:%會出現在URI中,但它本身需要被編碼。
看得很混亂看看例子吧:
標記:
var str="-_.!~*‘()";
var a=encodeURI(str);
document.writeln(a); 輸出==>-_.!~*‘()
var b=encodeURIComponent(str);
document.writeln(b); 輸出==>-_.!~*‘()
保留字:
var str=";/?:@&=+$,";
var a=encodeURI(str);
document.writeln(a); 輸出==>;/?:@&=+$,
var b=encodeURIComponent(str);
document.writeln(b); 輸出==>%3B%2F%3F%3A%40%26%3D%2B%24%2C
URI拒絕字元:
var str="<>#%<>";
var a=encodeURI(str);
document.writeln(a); 輸出==>%3C%3E#%25%3C%3E 注意: #沒被編碼
var b=encodeURIComponent(str);
document.writeln(b); 輸出==>%3C%3E%23%25%3C%3E
何時會使用到encodeURI()與encodeURIComponent():
最常接觸的大概就是AJAX吧,AJAX就是用傳遞網址來要求資料。
看個例子吧:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JSON/Atom Custom Search API Example</title>
</head>
<body onload="test();">
<div id="content"></div>
<script type="text/javascript">
var xmlhttp;
xmlhttp = new XMLHttpRequest(); //舊型IE不支援這作法
function showwho()
if(xmlhttp.readyState == 4 && xmlhttp.status == 200)
document.getElementById(‘content‘).innerHTML = xmlhttp.responseText;
function test()
var name = ‘維克‘;
url = ‘test.php?who=‘ + name + "&time=" + new Date().getTime();
xmlhttp.open(‘GET‘, url, true);
xmlhttp.onreadystatechange = showwho;
xmlhttp.send(null);
</script>
</body>
</html>
PHP:
<?php
echo($_GET[‘who‘]);
?>
這在IE9測試的結果,會出現亂碼!但在chrome是正常顯示的。
位時麼會這樣?
因為"維克"不是個URI的標準字元,PHP的GET認為所有非法URI字元都應該已經被編碼。
所以在處理時也會在解碼回來。沒編碼過的字元被解碼傳回來,結果就變亂碼了。
那為啥Chrome可以正常顯示?
因為Chrome在傳遞網址時會自動將非法的URI字元編碼!
聽說IE經過設定後也可以自動編碼URI非法字元,
但是即便如此瀏覽器依賴的程式設計並不是個好主意。
確保的做法是,對"維克"做encodeURIComponent ()的動作。
var name = ‘維克‘;
name=encodeURIComponent(name);
然後再傳出去!
傳遞表單時其實也會用到URI編碼。
表單傳遞其實有內建編碼傳遞方式,application/x-www-form-urlencoded
這邊碼方式並不標準,但接受度很廣..
有空閒在來多寫一些例子,先這樣吧!~~~~
沒寫到的:
1. encodeURI()跟encodeURIComponent ()都認定輸入字串為UTF-8做編碼。
並不作轉碼的動作,請確定你給他的字串是UTF-8編碼。
2.ECMA-262 5.1 Edition June/2011 支援的URI版本是RFC2396 而不是較新的RFC3986
3.在google 例子中出現的#是代表片段標識符
4.URI其實還滿複雜的,我都不太懂==",反正encodeURI就對了。
來自http://tools.ietf.org/html/rfc2396的部分原文:
An absolute URI contains the name of the scheme being used (<scheme>)
followed by a colon (":") and then a string (the <scheme-specific-
part>) whose interpretation depends on the scheme.
The URI syntax does not require that the scheme-specific-part have
any general structure or set of semantics which is common among all
URI. However, a subset of URI do share a common syntax for
representing hierarchical relationships within the namespace. This
"generic URI" syntax consists of a sequence of four main components:
<scheme>://<authority><path>?<query>
以上是关于为什麼encodeURI/encodeURIComponent()要调用两次来进行转码?的主要内容,如果未能解决你的问题,请参考以下文章
JS escape encodeURI encodeURIComponent用法