js與ASP.NET 中文亂碼問題
更新時間:2009年10月21日 14:09:23 作者:
本文摘自一位哥們的QQ空間里,自認為方案比較可行,也確實解決了開發(fā)中的這一類問題,非原創(chuàng),寫在此是為以后自己能方便的找到,也希望對其他的朋友有幫助。
1. 客戶端 -> 服務端的問題
1.1. get 方式提交短數(shù)據(jù)效率比 post 方式高
原因:個人感覺
1.2. post 方式提交時,若數(shù)據(jù)中含有中文,則服務端獲得的數(shù)據(jù)中文部分會變?yōu)閬y碼
原因: 可能是提交時 XMLHttpRequest 自動對非標準 ASCII 字符進行了編碼。
可能只是簡單的逸碼轉換,但具體編碼方式不詳, 在服務端就很難還原。
解決:(a) 在客戶端提交前,對串中的非標準 ASCII 字符用 escape() 手動轉碼。
這種方法對非標碼位置比較有規(guī)律(比如存放在不同的變量中)的情況比較合適。
在服務端獲取后無須用 unescape() 轉換即可正常處理。
(b) 對非標碼多而不方便分別 escape() 的,可以用 encodeURI() 兩次(是兩次,不是一次)。
服務端獲取后用 decodeURI() 一次即得到原正確內容。
疑惑:
以上兩個解決方法經(jīng)測試都正確可行。
有個疑惑就是,瀏覽器在提交數(shù)據(jù)的時候,看起來是對非標碼進行了一次轉換,
而在服務端獲取時(如 Request(), getAttribute() 等),看起來又偷偷進行了一次逆向轉換。
而這兩次轉換似乎沒有遵循同樣的標準,從而對非標碼的默認轉換會導致取不到正確的內容。
而在客戶端 escape() 后,服務端的逆轉換結果就是正確的??上?escape() 會對串中的所有可轉換
字符都進行轉換,而標準 ASCII 碼轉換后,在服務端取出來又成了錯的了(神奇....)。
所以 escape() 僅適合用來轉非標碼。
終極解決方案就是,在客戶端進行連續(xù)的兩次 encodeURI()。
這個規(guī)律是從分析服務端轉碼后的結果串得到的。
比如‘中'字,在 encodeURI() 一次后被轉碼為‘%E4%B8%AD',而在服務端手動進行一次
decodeURI() 卻得到了亂碼,猜想會不會是 Request() 偷偷進行那一次轉碼把不該轉的重要標志
‘%'也轉掉了,于是在客戶端多做一次 encodeURI(),此時‘中'字的轉碼結果就成了
‘%25E4%25B8%25AD',25h 恰好便是‘%',這樣一來,服務端偷轉一次,把‘%25'解為
‘%',再由手動 decodeURI() 轉的時候,串已經(jīng)變成了‘%E4%B8%AD',這樣就得到了正確的
內容。
好像沒有說清楚,不過我是明白了,希望以后忘掉的時候也能再看懂。
2. 服務端 -> 客戶端的問題
2.1. 回轉含有中文的數(shù)據(jù)時,客戶端收到的是亂碼
原因: 肯定是頁面編碼的問題,因為我的前提就是不強求使用統(tǒng)一的編碼,所以這個問題要解決。
解決: 太簡單,只需要在服務端向客戶端回寫數(shù)據(jù)前任何地方設置 Response.Chartset = "gb2312" 即可,
不需要像很多討論到的要轉碼甚至有人寫出大段的轉碼程序,當然,客戶端如果是別的編碼方式,
改一下就行了。
2.2. 客戶端用 JSON 方式處理接收數(shù)據(jù)時,eval() 函數(shù)不能正確地把收到的數(shù)據(jù)解釋為代碼片段
比如用 var obj = eval( "{ p1:1, p2:2 }" ) 這樣的形式,obj 是不能正確被初始化為對象實例的,而是會
收到一個缺少分號的錯誤,而用 eval( "var obj = { p1:1, p2:2 }" ) 這樣的形式,就能正確地生成一個
obj 的有效對象實例。
其實仔細想一下,似乎也對,eval() 并不是如書上所講,直接把串作為代碼的一部分插入到整個代碼
段中,而是返回轉入的表達式的值,而以‘{...}'的形式定義的空函數(shù)對象,其表達式值本身是
undefined,而若其中成員多于一個,則此表達值根本不能作為合法語法獨立存在,所以才會報錯;
而后一種形式,其實質其實是一個賦值表達式,雖然前綴了 var 會導致整個表達式值為 undefined,
但此過程中卻真實地生成了 obj 對象實例。在之后的上下文中引用 obj 就是有效的了。
經(jīng)過實驗看來,書上和部分前輩文章提到的第一種用法,其實是不能正確工作的,至少在我的機器
上,它確實失敗了。當然,不能不考慮有可能是我的瀏覽器甚至是 OS 本身的原因,這個就深了。
解決:不管有多深,問題總是要解決的。也很簡單,只需要按第二種形式,把接收變量的定義一起放
到 eval() 中,即可正常工作。
另外,回轉 JSON 數(shù)據(jù)時,也要考慮B/S雙方編碼問題,如果不一致,按 2.2 中的方法即可解決。
很重要的一點是,有時候 debug 或 trace 出來的結果,特別是字符串,看起來確實是正確的,但就
是不能正常工作,那時候就需要從編碼的層次去驗證,而不要僅僅考慮代碼本身邏輯的問題。因為有
些非打印編碼,在 debug 和 trace 時都是不會被回顯到屏幕上的?!把垡姺菍崱保@一點,在任何
地方永遠適用。
綜合感受
Ajax 作為一種技術,其本身并無先進之處,相反過多地依賴和信仰會令其成為開發(fā)中的累贅,大量
的精力耗費在基礎工作中,思路游離于業(yè)務邏輯之外,這是一件好事,可以令你的工作更快地以失敗
告終。
但,Ajax 作為一種思想,反而是值得推崇的,這種思想,早已經(jīng)由賣童裝的美特斯邦威作出了精辟
的概括——不走尋常路。
數(shù)年來,在世界各地,
有 80% 的開發(fā)人員沒有想到在 submit 之外去找路,他們是幸福的,他們走在一條熟悉的路上。
另外 10% 的人走在了 iframe 的路上,他們是幸運的,他們找到了一條風景更加美好的路。
另外 8% 的人在草叢中發(fā)現(xiàn)了 XMLHttpRequest,他們是值得尊敬的,他們替人們找到了新的路。
另外 2% 的人把這條新路命名為 Ajax,他們是偉大的,他們替人們找到了加班到累死的理由。
1.1. get 方式提交短數(shù)據(jù)效率比 post 方式高
原因:個人感覺
1.2. post 方式提交時,若數(shù)據(jù)中含有中文,則服務端獲得的數(shù)據(jù)中文部分會變?yōu)閬y碼
原因: 可能是提交時 XMLHttpRequest 自動對非標準 ASCII 字符進行了編碼。
可能只是簡單的逸碼轉換,但具體編碼方式不詳, 在服務端就很難還原。
解決:(a) 在客戶端提交前,對串中的非標準 ASCII 字符用 escape() 手動轉碼。
這種方法對非標碼位置比較有規(guī)律(比如存放在不同的變量中)的情況比較合適。
在服務端獲取后無須用 unescape() 轉換即可正常處理。
(b) 對非標碼多而不方便分別 escape() 的,可以用 encodeURI() 兩次(是兩次,不是一次)。
服務端獲取后用 decodeURI() 一次即得到原正確內容。
疑惑:
以上兩個解決方法經(jīng)測試都正確可行。
有個疑惑就是,瀏覽器在提交數(shù)據(jù)的時候,看起來是對非標碼進行了一次轉換,
而在服務端獲取時(如 Request(), getAttribute() 等),看起來又偷偷進行了一次逆向轉換。
而這兩次轉換似乎沒有遵循同樣的標準,從而對非標碼的默認轉換會導致取不到正確的內容。
而在客戶端 escape() 后,服務端的逆轉換結果就是正確的??上?escape() 會對串中的所有可轉換
字符都進行轉換,而標準 ASCII 碼轉換后,在服務端取出來又成了錯的了(神奇....)。
所以 escape() 僅適合用來轉非標碼。
終極解決方案就是,在客戶端進行連續(xù)的兩次 encodeURI()。
這個規(guī)律是從分析服務端轉碼后的結果串得到的。
比如‘中'字,在 encodeURI() 一次后被轉碼為‘%E4%B8%AD',而在服務端手動進行一次
decodeURI() 卻得到了亂碼,猜想會不會是 Request() 偷偷進行那一次轉碼把不該轉的重要標志
‘%'也轉掉了,于是在客戶端多做一次 encodeURI(),此時‘中'字的轉碼結果就成了
‘%25E4%25B8%25AD',25h 恰好便是‘%',這樣一來,服務端偷轉一次,把‘%25'解為
‘%',再由手動 decodeURI() 轉的時候,串已經(jīng)變成了‘%E4%B8%AD',這樣就得到了正確的
內容。
好像沒有說清楚,不過我是明白了,希望以后忘掉的時候也能再看懂。
2. 服務端 -> 客戶端的問題
2.1. 回轉含有中文的數(shù)據(jù)時,客戶端收到的是亂碼
原因: 肯定是頁面編碼的問題,因為我的前提就是不強求使用統(tǒng)一的編碼,所以這個問題要解決。
解決: 太簡單,只需要在服務端向客戶端回寫數(shù)據(jù)前任何地方設置 Response.Chartset = "gb2312" 即可,
不需要像很多討論到的要轉碼甚至有人寫出大段的轉碼程序,當然,客戶端如果是別的編碼方式,
改一下就行了。
2.2. 客戶端用 JSON 方式處理接收數(shù)據(jù)時,eval() 函數(shù)不能正確地把收到的數(shù)據(jù)解釋為代碼片段
比如用 var obj = eval( "{ p1:1, p2:2 }" ) 這樣的形式,obj 是不能正確被初始化為對象實例的,而是會
收到一個缺少分號的錯誤,而用 eval( "var obj = { p1:1, p2:2 }" ) 這樣的形式,就能正確地生成一個
obj 的有效對象實例。
其實仔細想一下,似乎也對,eval() 并不是如書上所講,直接把串作為代碼的一部分插入到整個代碼
段中,而是返回轉入的表達式的值,而以‘{...}'的形式定義的空函數(shù)對象,其表達式值本身是
undefined,而若其中成員多于一個,則此表達值根本不能作為合法語法獨立存在,所以才會報錯;
而后一種形式,其實質其實是一個賦值表達式,雖然前綴了 var 會導致整個表達式值為 undefined,
但此過程中卻真實地生成了 obj 對象實例。在之后的上下文中引用 obj 就是有效的了。
經(jīng)過實驗看來,書上和部分前輩文章提到的第一種用法,其實是不能正確工作的,至少在我的機器
上,它確實失敗了。當然,不能不考慮有可能是我的瀏覽器甚至是 OS 本身的原因,這個就深了。
解決:不管有多深,問題總是要解決的。也很簡單,只需要按第二種形式,把接收變量的定義一起放
到 eval() 中,即可正常工作。
另外,回轉 JSON 數(shù)據(jù)時,也要考慮B/S雙方編碼問題,如果不一致,按 2.2 中的方法即可解決。
很重要的一點是,有時候 debug 或 trace 出來的結果,特別是字符串,看起來確實是正確的,但就
是不能正常工作,那時候就需要從編碼的層次去驗證,而不要僅僅考慮代碼本身邏輯的問題。因為有
些非打印編碼,在 debug 和 trace 時都是不會被回顯到屏幕上的?!把垡姺菍崱保@一點,在任何
地方永遠適用。
綜合感受
Ajax 作為一種技術,其本身并無先進之處,相反過多地依賴和信仰會令其成為開發(fā)中的累贅,大量
的精力耗費在基礎工作中,思路游離于業(yè)務邏輯之外,這是一件好事,可以令你的工作更快地以失敗
告終。
但,Ajax 作為一種思想,反而是值得推崇的,這種思想,早已經(jīng)由賣童裝的美特斯邦威作出了精辟
的概括——不走尋常路。
數(shù)年來,在世界各地,
有 80% 的開發(fā)人員沒有想到在 submit 之外去找路,他們是幸福的,他們走在一條熟悉的路上。
另外 10% 的人走在了 iframe 的路上,他們是幸運的,他們找到了一條風景更加美好的路。
另外 8% 的人在草叢中發(fā)現(xiàn)了 XMLHttpRequest,他們是值得尊敬的,他們替人們找到了新的路。
另外 2% 的人把這條新路命名為 Ajax,他們是偉大的,他們替人們找到了加班到累死的理由。
相關文章
ASP.NET?Core使用EF創(chuàng)建模型(包含屬性、排除屬性、主鍵和生成值)
這篇文章介紹了ASP.NET?Core使用EF創(chuàng)建模型的的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-04-04.Net Core創(chuàng)建Api進行文件上傳功能
這篇文章主要介紹了.Net Core創(chuàng)建Api進行文件上傳,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-03-03.NET Core利用swagger進行API接口文檔管理的方法詳解
這篇文章主要給大家介紹了關于.NET Core利用swagger進行API接口文檔管理的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。2018-03-03vs2012創(chuàng)建的ado.net模型無法實例化的解決方案
本文給大家分享的是升級vs2012后,發(fā)現(xiàn)創(chuàng)建數(shù)據(jù)模型無法實例化使用,嘗試了很多種方法,最后在度娘的幫助下,才解決了這個問題,這里記錄下來,分享給大家。2015-03-03