AJAX在GB2312的中文編碼傳輸 AJAX特殊字元編碼正確方法_AJAX相關

來源:互聯網
上載者:User
很多可能在轉摘過程中失真或未經驗證就被轉摘,真正使用時卻不行,也由此決定自己全方位實驗一下,努力還是沒有白費,雖然最終得出的結果是很簡單的,但其過程對於一個新學AJAX的人來說,真是挺累。
歡迎您在使用過程中對新的心得一起跟帖交流,一個思想+一個思想,至少可以產生兩個思想。

一、在GET發送時:

方法1:在ASP伺服器端用Response.charset="GB2312"界定輸出編碼給調用用戶端
此時用戶端不需要做什麼轉換即可。如下兩個檔案:
1、用戶端JS
複製代碼 代碼如下:

var xmlHttp;
function createXML(){
if(window.ActiveXObject){
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}else if(window.XMLHttpRequest){
xmlHttp=new XMLHttpRequest();
}
}
function startXml(){
createXML();
xmlHttp.onreadystatechange = handleStateChange;
var url="ajaxtext.asp?tm=1&cc"+Math.random();
//var sendContents = 'theinput='+escape(theinput.value);
var regcode="2abc";
xmlHttp.open("get",url,true);
//regcode="regcode="+regcode;
//xmlHttp.setrequestheader("content-length",regcode.length); //可加可不加
//xmlHttp.setRequestHeader("Cache-Control","no-cache");
//xmlHttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); //可不加
//xmlHttp.send(null);
//xmlHttp.send("regcode="+escape(regcode));
xmlHttp.send(null);
}
function handleStateChange(){
if (xmlHttp.readyState == 4 && xmlHttp.status==200){
//var divid=document.getElementById("results");
retext=xmlHttp.responseText;
alert(retext);
//if(divid.hasChildNodes()){
// divid.removeChild(divid.childNodes[0]);
//}
//var result=document.createTextNode(xmlHttp.responseText);
//divid.appendChild(result);
//document.getElementById("results").innerHTML=xmlHttp.responseText;
}
}

伺服器端:
複製代碼 代碼如下:

<%Response.CodePage=936%>
<%Response.charset="GB2312"
dim reg
reg=Request("regcode")
Response.write "王先生·和他的朋友" '可以正確輸出。
%>

方法2:在用戶端用函數轉換(來自網上)。
複製代碼 代碼如下:

function gb2utf8(data){
var glbEncode = [];
gb2utf8_data = data;
execScript("gb2utf8_data = MidB(gb2utf8_data, 1)", "VBScript");
var t=escape(gb2utf8_data).replace(/%u/g,"").replace(/(.{2})(.{2})/g,"%$2%$1").replace(/%([A-Z].)%(.{2})/g,"@$1$2");
t=t.split("@");
var i=0,j=t.length,k;
while(++i<j) {
k=t[i].substring(0,4);
if(!glbEncode[k]) {
gb2utf8_char = eval("0x"+k);
execScript("gb2utf8_char = Chr(gb2utf8_char)", "VBScript");
glbEncode[k]=escape(gb2utf8_char).substring(1,6);
}
t[i]=glbEncode[k]+t[i].substring(4);
}
gb2utf8_data = gb2utf8_char = null;
return unescape(t.join("%"));
}

此時如果伺服器端不指明編碼,那麼AJAX預設為UTF-8,就不能在用戶端顯示,用這個函數就可以。
複製代碼 代碼如下:

retext=xmlHttp.responseText;
retext=gb2utf8(retext);
alert(retext);

3、在Firefox瀏覽器下:具體請參考:下一篇文章

Firefox比較簡單,他可以支援xmlHttp.responseText;//FireFox,但為了代碼簡化,建議用上面的直接做好編碼。
但如果為了通用,就按POST下面介紹的方法來做吧。

二、在POST發送時:

對於常規的中文,上述的GET方法在POST也是可以的,但網上有一篇文章提到了部分符號不能顯示的,比如:下一篇文章中的“test·test+test·”,(中間是間隔號)測試過了,的確在伺服器端界定編碼後輸出給用戶端也不能顯示。

如果按照文中所說的,
發送端用xmlHttp.send("regcode="+escape(regcode));

然後在伺服器端將接收的資料套上兩個編碼encodeURIComponent(escape(xxxxxxx)),則顯示的結果是:test%25u7A5Eest%2520test,同樣不行。另外這個思路應是不對的,不知道這篇文章在網上被轉抄時是否本身就有錯,按理在用戶端用escape編碼傳送後,在伺服器端就應該反編碼。或者REQUEST本身就有解碼的作用。不需要再二次、三次編碼。況且查了一下,escape和encodeURIComponent也無法對特殊字元編碼。

我在伺服器端做了如下輸出:
複製代碼 代碼如下:

test2="test·test+test·回饋:"
Response.write test2&"前面是伺服器直接輸出的而非接收的特殊符號“·”間隔號。後面是接收的資料(內容與原AJAX發送的一樣,用於對比):"

也就是說直接在伺服器端產生一個同樣的含特殊字元,這個伺服器端檔案已經用<%Response.charset="GB2312"%>定義好編碼為GB2312。但輸出的結果是,在伺服器端產生的test2="test·test+test·回饋:"可以正常輸出,而接收的AJAX值就不行了。
即使在用戶端用JS三個編碼參數escape()\encodeURI() \encodeURIComponent() 全部試過去,然後在伺服器商反編碼再輸出,也是不行。這說明字串中的特殊符號在伺服器端接收時就已經變形了。

現在問題界定在編碼傳遞上了,為了說明這個問題,我又做了一個小實驗:就是把這個字串賦值給ASP的一個變數再用ASP變數來賦值給JS,如下:
複製代碼 代碼如下:

<%
para="test·test+test·/"
para=Server.urlencode(para)
%>

然後轉手給JS變數,如下:
複製代碼 代碼如下:

xmlHttp.open("POST",url,true);
var regcode="<%=para%>";
xmlHttp.setRequestHeader('Content-type','application/x-www-form-urlencoded;charset=gb2312');
xmlHttp.send("regcode="+regcode);

結果正常了,這充分說明ASP的server.urlencode能完整對特殊字元編碼。而JS還是有欠缺。

那現在怎麼辦?

在實在沒辦法的情況下,我想到了即然encodeURIComponent()可以比encode()對更多特殊字元編碼,那麼不妨像多重MD5加密一樣,增加強化劑,於是我套用了兩個encodeURIComponent(),現在代碼是:
複製代碼 代碼如下:

var regcode="test·test+test·/";
xmlHttp.setRequestHeader('Content-type','application/x-www-form-urlencoded;charset=gb2312');
xmlHttp.send("regcode="+encodeURIComponent(encodeURIComponent(regcode)));

上面是用戶端的,再把伺服器端改成:
複製代碼 代碼如下:

<script language="javascript" runat="server">
function decodestr(str){
return decodeURIComponent(decodeURIComponent(str));
}
</script>
<%
dim reg
reg=Request("regcode")
test2="test·test+test·回饋:"
Response.write test2&"前面是服務直接輸入的而非接收的特殊符號“·”間隔號。後面是接收的資料(內容與原AJAX發送的一樣,用於對比):"
Response.write decodestr(reg)
%>

終於完美看到了AJAX輸出的特殊字元。間隔號和+號都出來了,
“test·test+test·/”
為了進一步驗證,我把下面encodeURIComponent也無法編碼的個別特殊字元全加進來了,如下:
複製代碼 代碼如下:

var regcode="漢字開頭:! @ # $& * ( ··) = : / ; ? + 結尾,中間全是特殊字元。";

結果也正常了,太棒!
不過一般AJAX傳給伺服器的資料是要應用的,否則沒有意義,為了再進一步驗證資料是否一樣,我把伺服器端做了小修改,如下:
複製代碼 代碼如下:

<%
dim reg
reg=Request("regcode")
test2="漢字開頭:! @ # $& * ( ··) = : / ; ? + 結尾,中間全是特殊字元。"
IF test2<>decodestr(reg) Then
Response.write "不同"
Else
Response.write "相同"
End IF
%>

很興奮。用戶端輸出“相同”,這下可以放心全面應用了。

總結:

1、AJAX用戶端雙重套用encodeURIComponent()對POST的資料編碼。
2、伺服器端對應地用decodeURIComponent()雙重解碼即可:
<script language="javascript" runat="server">
function decodestr(str){
return decodeURIComponent(decodeURIComponent(str));
}
</script>
3、在接收responseText時,不需要再反編碼了。直接:retext=xmlHttp.responseText;
4、伺服器端的這行仍然不可缺:<%Response.charset="GB2312"%>,一般在ASP檔案中,都有<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%>這行,但這行可以去掉,唯獨不能去掉<%Response.charset="GB2312"%>,否則出錯。

現在開始,把encodeURIComponent()/decodeURIComponent()背熟就可以。
附:以下幾個編碼方法摘自JS手冊,供參考:

escape() 方法:
採用ISO Latin字元集對指定的字串進行編碼。所有的空格符、標點符號、特殊字元以及其他非ASCII字元都將被轉化成%xx格式的字元編碼(xx等於該字元在字元集表裡面的編碼的16進位數字)。比如,空格符對應的編碼是%20。unescape方法與此相反。不會被此方法編碼的字元: @ * / +

注釋:可以使用 unescape() 對 escape() 編碼的字串進行解碼。但ECMAScript v3 反對使用這種方法,應用使用 decodeURI() 和 decodeURIComponent() 替代它。

encodeURI() 方法: ------ 注意後面一個是大小的i——“I”不是L,下面的decodeURI也不是L。
把URI字串採用UTF-8編碼格式轉化成escape格式的字串。不會被此方法編碼的字元:! @ # $& * ( ) = : / ; ? + '

encodeURIComponent() 方法:
把URI字串採用UTF-8編碼格式轉化成escape格式的字串。與encodeURI()相比,這個方法將對更多的字元進行編碼,比如 / 等字元。所以如果字串裡麵包含了URI的幾個部分的話,不能用這個方法來進行編碼,否則 / 字元被編碼之後URL將顯示錯誤。不會被此方法編碼的字元:! * ( )


引用內容
因此,對於中文字串來說,如果不希望把字串編碼格式轉化成UTF-8格式的(比如原頁面和目標頁面的charset是一致的時候),只需要使用escape。如果你的頁面是GB2312或者其他的編碼,而接受參數的頁面是UTF-8編碼的,就要採用encodeURI或者encodeURIComponent。
另外,encodeURI/encodeURIComponent是在javascript1.5之後引進的,escape則在javascript1.0版本就有。

decodeURI() 函數
decodeURI() 函數可對 encodeURI() 函數編碼過的 URI 進行解碼。
<script type="text/javascript">

var test1=http://www.w3school.com.cn/My first/
document.write(encodeURI(test1)+ "<br />")
document.write(decodeURI(test1))
</script>

decodeURIComponent() 函數:可對 encodeURIComponent() 函數編碼的 URI 進行解碼。
unescape():對escape解碼。
作者:非物理生命部落格traindiy
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.