AJAX 請求傳遞中文參數時,編碼不一致是導致亂碼的主因。本文針對「頁面編碼為 GB2312/Big5,AJAX 預設以 UTF-8 發送」的經典場景,提供經實測在 IE 與 Firefox 均正常運作的完整解決方案,涵蓋前端編碼、後端解碼與轉碼的雙重處理流程。
XMLHttpRequest 發送資料時預設以 UTF-8 編碼// 取得使用者輸入或欲發送的中文參數
var param = document.getElementById('keyword').value;
// 必須雙重 encodeURI!單次在 IE 會導致參數值為空
param = encodeURI(encodeURI(param));
// 或寫成兩行
// param = encodeURI(param);
// param = encodeURI(param);
var url = 'search.php?kw=' + param;
xmlhttp.open('GET', url, true);
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlhttp.send(null);
為什麼要雙重編碼?
IE 在送出前會自動依頁面編碼(如 GB2312)對 URL 進行一次編碼,Firefox 不會。若只 encodeURI 一次:
- Firefox:送出 UTF-8 編碼 → 正常
- IE:送出「UTF-8 編碼後再 GB2312 編碼」→ 後端解碼失敗
雙重編碼後,Firefox 送出「雙重 UTF-8」,IE 送出「雙重 UTF-8 + GB2312」,後端統一做「URL 解碼 → UTF-8 轉目標編碼」即可雙贏。
<?php
header('Content-Type: text/html; charset=GB2312'); // 宣告回應編碼
$kw = $_GET['kw'] ?? '';
// 1. 先 URL 解碼(還原雙重編碼)
$kw = urldecode($kw);
// 2. 再由 UTF-8 轉目標編碼(GB2312/Big5/UTF-8)
$kw = iconv('UTF-8', 'GB2312//IGNORE', $kw);
// 現在 $kw 可正常用於 SQL 查詢、輸出等
$sql = "SELECT * FROM products WHERE name LIKE '%$kw%'"; // 實務請用預處理
?>
順序鐵律:urldecode() 必須在 iconv() 之前!反之會產生錯誤字元導致轉碼失敗。
若伺服器回應中文給 AJAX,需明確宣告回應編碼:
<?php
// PHP
header('Content-Type: text/html; charset=UTF-8'); // 或 GB2312
echo "中文內容";
或在 AJAX 回呼中強制指定:
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// 若回應為 XML
var xmlDoc = xmlhttp.responseXML;
// 若回應為純文字
var text = xmlhttp.responseText;
}
};
新專案強烈建議:
utf8mb4<meta charset="UTF-8">header('Content-Type: application/json; charset=UTF-8')encodeURIComponent() 單次即可全鏈路 UTF-8 可徹底消除編碼地獄,僅在維護舊系統時需用本文方案。
encodeURI(encodeURI()) 雙重編碼?urldecode() 再 iconv()?iconv 目標編碼是否與頁面/資料庫一致?iconv 加上 //IGNORE 或 //TRANSLIT 避免非法字元中斷?