一個UTF8頁面需要POST資料到GB2312頁面,這時中文的編碼是按照UTF8提交過去的,GB2312頁面無法接收。如何?,網路搜尋了一種很不錯的方法,但有缺陷,這裡一一說起。
1、FORM標籤裡加上accept-charset代碼,這個能把FORM裡的資料自動編碼成指定的字元集提交,比如在UTF8頁面提交資料到GB2312,代碼就是accept-charset=”GB2312″,但accept-charset除了IE其他瀏覽器都支援。。。
2、這時可以在提交時觸發JS,document.charset=’GB2312′;,用這段代碼設定當前頁面編碼為GB2312。到這裡看似很完美了,但還一個問題,就是觸發這個代碼後,當前頁面重新整理之後會亂碼,這是因為你剛才改變了當前頁面的編碼。
3、怎麼處理重新整理後亂碼呢,就是要加以判斷,判斷當前頁面編碼和預設的編碼是否一致,如果不一致則重新整理,
代碼如下 |
複製代碼 |
if(isIE && document.charset!=”utf-8″)location.reload(false) |
4、網上的介紹最多到這步,但是我卻發現,這樣就步入了一個死迴圈,因為第2步已經改變了編碼,您在當前頁面不管怎樣重新整理,還是改變後的編碼,所以一定要重設這個編碼才行,代碼就是這樣的。
代碼如下 |
複製代碼 |
if(isIE && document.charset!=”utf-8″){ document.charset=’utf-8′; location.reload(false);} |
代碼綜合起來如下:
判斷當前頁碼是否為UTF8,如果不是,則設定編碼為UTF8並重新整理,避免亂碼。
代碼如下 |
複製代碼 |
var isIE=!!window.ActiveXObject; if(isIE && document.charset!=”utf-8″){ document.charset=’utf-8′; location.reload(false);} |
設定FORM的accept-charset,讓非IE瀏覽器直接提交編碼後的資料到其他頁面
代碼如下 |
複製代碼 |
<form accept-charset=”GB2312″> |
提交資料時觸發修改當前頁面編碼的JS
代碼如下 |
複製代碼 |
onsubmit=”if(isIE)document.charset=’GB2312′” |
執行個體
方法其實很簡單:
比如頁面表單(form)代碼如下:
代碼如下 |
複製代碼 |
<form name="formname"method="post" action=""> …… </form> |
只需要在該頁面增加javascript函數,比如:
代碼如下 |
複製代碼 |
function functionname() { document.charset="gb2312"; formname.submit(); } |
最後,將這個函數增加到form的onsubmit中即可。即:
代碼如下 |
複製代碼 |
<form name="formname"method="post" action="" onsubmit=“functionname();”> …… </form> |
讓我們先看一下AJAX 的經典請求代碼
代碼如下 |
複製代碼 |
xmlhttp.open( "post", url, async ); xmlhttp.setRequestHeader( "Content-Type", "text/html" ); xmlhttp.send( params ); |
通過前面的說明,不知道你現在看出端倪了沒有。不知道是受了網上教程的影響還是其它方面影響,setRequestHeader 並是萬年不變的,也沒人想過去改它,而問題就正好出在這個地方。回想一個JSP 頁面內容的編碼設定,其中有這麼一節:
代碼如下 |
複製代碼 |
contentType="text/html; charset=UTF-8" |
現在知道問題了吧,所以我們要把第二句代碼改為:
代碼如下 |
複製代碼 |
xmlhttp.setRequestHeader( "Content-Type", "text/html;charset=UTF-8" ); |
如果提交的是form ,那麼設定為
代碼如下 |
複製代碼 |
"application/x-www-form-urlencoded; charset=UTF-8" |
最後別忘了在返回資料時也設定上:
代碼如下 |
複製代碼 |
response.setContentType( "text/xml" ); response.setCharacterEncoding( "UTF-8" ); |
如果要問為什麼的話,其實我們可以把xmlhttp 看成是一個臨時頁面,它由瀏覽器動態產生,主要作用是在後台獲得請求的資料(可以看成是一個進階的iframe )。所以對於普通版面設定的編碼,對它也要同樣設定。而在servlet 中返回資料為什麼要設定contentType 和encoding 其道理也是一樣的。眾所周知,jsp 的最後形態就是servlet ,而jsp 頁首設定的那個內容其實也就是讓產生的servlet 中產生這麼兩句話:
代碼如下 |
複製代碼 |
response.setContentType( "text/html" ); response.setCharacterEncoding( "UTF-8" ); |
而pageEncoding 則是跟jvm 說明了這個頁面的內容要使用什麼編碼儲存(這跟之後產生的CLASS 有關係)。所以在servlet 設定response 的編碼也是理所當然的了。
代碼如下 |
複製代碼 |
response.setContentType("text/xml;charset=UTF-8"); response.setHeader("Pragma", "no-cache"); //HTTP 1.0 response.setDateHeader("Expires", 0); //prevents caching at the proxy server PrintWriter out = response.getWriter(); out.write(outXML); out.flush(); out.close(); |
OK !這樣向用戶端寫的資料中的中文也是UTF-8 編碼了,用戶端js 指令碼擷取到request.responseXML 也好,responseText 也好,裡面的資料都不會有亂碼了
7)解決json在後台傳遞中的亂碼:
a.Action:
代碼如下 |
複製代碼 |
PrintWriter out = response.getWriter(); out.print("啊"); |
b.action:
代碼如下 |
複製代碼 |
BufferedReader bf = new BufferedReader(new InputStreamReader(httppost.getResponseBodyAsStream())); |
這裡得到的bf.readline會是亂碼,解決辦法為:
在a.Action中 PrintWriter out = response.getWriter(); 前面加上
代碼如下 |
複製代碼 |
response.setCharacterEncoding("UTF-8"); |
在b.Action中修改為
代碼如下 |
複製代碼 |
BufferedReader bf = new BufferedReader(new InputStreamReader(httppost.getResponseBodyAsStream(),"UTF-8")); |
總結
其實我們只要頁面與儲存資料頁面編碼統計就是了,同時ajax預設提交資料編碼為utf-8的,如果你是GBK的頁面我們只要把發送編碼修改一下即可。
中文亂碼原因在於javascript使用的是UTF-8國際編碼,UTF-8每個漢字用4個位元組來儲存。而我的頁面和資料庫都用GB2312編碼,這就造成了AJAX send資料的時候出現中文亂碼的問題