先後端傳參過程當中不得不面對的轉碼問題

數據傳遞轉碼
數據在傳輸的過程當中,瀏覽器會對數據進行編碼,假如我如今有一條數據 {"name": "測試"},若是咱們經過 get 方法傳遞數據,這條數據會被拼接到 url 請求的後面,如:localhost:8080/src/text.html?name=測試。html

uri自己是採用ASCII編碼的,因此若是是非 ASCII 編碼集的字符在傳輸時都會被編碼,編碼方法和 encodeURI 的編碼規則相同,可是這裏的編碼規則是由瀏覽器控制的,不一樣的瀏覽器採用的編碼方式 (UTF-8,GBK) 不同,被編碼的數據發送給服務器,服務器用 iso-8859-1 編碼對數據解碼,後端人員經過 request.getParameter("name") 獲取參數數據,且得到的數據都是通過解碼過的,而解碼過程當中程序裏沒法指定,對於 get 請求得到的數據 request.setCharacterEncoding("字符集") 指定解碼規則無效。前端

若是是 post 方法傳遞數據,瀏覽器也會對數據進行編碼,若是咱們在 ajax 請求頭裏面設置了 setRequestHeader("ContentType","application/x-www-form-urlencoded;charset=UTF-8"); 瀏覽器就會以charset值進行編碼,若是沒有設置則由網頁 meta 標籤的 charset 屬性決定,被編碼過的數據發送給服務器,服務器用 iso-8859-1 編碼對數據解碼,對於post請求發來的數據後端人員可使用
request.setCharacterEncoding("字符集") 指定解碼規則。ajax

相信你已經找出了亂碼的緣由,因爲 get 方法傳的的數據,瀏覽器的轉碼規則和服務器的解碼規則不一致出現了亂碼,咱們通常是怎麼解決的呢?get 方式發送的數據若是有中文和特殊字符前端會先使用 encodeURI() 方法轉碼,這樣 url 裏面的就都是 ASCII 編碼集的字符,省去了瀏覽器的轉碼,且 encodeURI() 的轉碼規則可控,受網頁 meta 頭的 charset 屬性影響,json

  1. 標籤的 charset 屬性爲 utf-8 時:
var data = '百度&%$#@baidu';
    console.log(encodeURI(data));
    // %E7%99%BE%E5%BA%A6&%25$#@baidu
    console.log(encodeURIComponent(data));
    // %E7%99%BE%E5%BA%A6%26%25%24%23%40baidu
  1. 標籤的 charset 屬性爲 GBK 時:
var data = '百度&%$#@baidu';
console.log(encodeURI(data));
// %E9%90%A7%E6%83%A7%E5%AE%B3&%25$#@baidu
console.log(encodeURIComponent(data));
// %E9%90%A7%E6%83%A7%E5%AE%B3%26%25%24%23%40baidu

後端人員獲取到用iso-8859-1解碼後的數據通常先還原回字節碼,而後用先後端協定的方式解碼數據,還能夠在服務器的配置文件裏面進行配置解碼規則。而post請求發送的數據可使用request.setCharacterEncoding("字符集")指定解碼規則來達到先後端轉碼統一。後端

當咱們須要傳遞的數據量大,結構複雜,業務場景,技術實現須要的時候咱們就又會發現,亂碼的問題依然存在,好比瀏覽器

  • json格式的數據因爲特殊字符致使數據解析出現問題,
  • xml格式數據因爲特殊字符破壞xml格式致使數據解析出現問題,
  • 先後端一些語言自帶的轉碼方法對一些特殊字符轉碼結果不一致,以及並不是全部特殊字符都會被轉碼...

若是咱們使用 encodeURI 或者 encodeURIComponent 編碼傳輸到後端,後端解碼以後的數據總會由於一些特殊字符的轉碼不一致致使結果不同,若是再加上 md5 校驗之類的,前端傳遞的數據就會由於 md5 不一樣沒法解析入庫。服務器

那麼這個時候咱們就該考慮有沒有一種轉碼規則能夠解決以上全部的問題呢?base64 轉碼你值得擁有。app

base64轉碼post

base64 編碼是從二進制到字符的過程,編碼受 html 頁面頭部 mate;標籤的 charset 屬性影響,charset 屬性不一樣,編碼轉爲二進制時,產生的二進制也是不同的,因此最終產生的 base64 字符也不同。測試

  1. mate 標籤的 charset 屬性爲 utf-8 時:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>base64</title>
</head>
<body>
<script src="base64.min.js"></script>
<script>
var data = '百度&%$#@baidu';
console.log(base64encode(data));
// fqYmJSQjQGJhaWR1
</script>
</body>
  1. mate 標籤的 charset 屬性爲 GBK 時:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="GBK">
<title>base64</title>
</head>
<body>
<script src="base64.min.js"></script>
<script>
var data = '百度&%$#@baidu';
console.log(base64encode(data));
// J+ezJiUkI0BiYWlkdQ==
</script>
</body>

有關 base64 轉碼原理有興趣可自行百科。

總結

因此工做中若是涉及到文本框輸入等複雜的內容數據傳遞爲了不中文亂碼以及各類特殊符號帶來的困擾就使用 base64 轉碼傳遞。 若是隻是URL裏面的傳遞簡單的參數可使用 encodeURI 和 encodeURIComponent 等轉碼。

相關文章
相關標籤/搜索