Ajax中文乱码解决方案
分类: 综合开发 2011-11-26 22:06:43 阅读(4562)
主流浏览器中 Ajax 对象请求时都以 UTF-8 编码发送数据,所以当前后端文件都统一用 UTF-8 编码时情况比较经典而单纯。如果确实需要 GB 字符集,则需要适当变通。这里就这两种字符集分别说明解决方案。服务器端文件以 PHP 举例。
下列方案在 IE 系、FireFox3、Chrome4、Opera10 测试通过。
UTF-8 经典方案
前后端文件本身统一都用 UTF-8 编码。
HTML 文件使用声明:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
JavaScript 文件也要存为 UTF-8 模式,最终确保传递参数始终以 UTF-8 编码的核心是把参数值统一用 encodeURIComponent() 处理。即 SF.HTTP.xhr_utf.js 中的如下这行
param = encodeURIComponent(param);
注意此时后台 PHP 程序接收到的请求数据是 UTF-8 编码的,如果需要转成其它字符集的数据可以用 iconv 进一步处理。PHP 程序输出数据也必须是 UTF-8 编码的,加声明:
header("text/html;charset=UTF-8");
注意要让 IE 正常接收 UTF8 的数据,必须写大写的"UTF-8",而不能用小写或其它写法!
以下是各文件完整的代码:
sfxhr_utf.htm
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>AJAX中文-UTF8版</title>
<script type="text/javascript" src="SF.HTTP.xhr_utf.js" mce_src="SF.HTTP.xhr_utf.js"></script>
</head>
<body>
<script type="text/javascript"></script>
</body>
</html>
SF.HTTP.xhr_utf.js
var SF =
{
//HTTP 请求相关
HTTP:
{
/**兼容 GB2312 字符集的 Ajax 调用方法
变通是用 escape,提交的汉字会变成 %u9886%u5730 这样的,后端程序再处理成GB字符集的中文,见 ajax.php 中的 unescape 函数。
输入参数,JSON 格式对象
{
'url': url, 请求的 URL
'type': method, 提交方式,get 或 post,默认为 get
'charset':charset, 字符集,默认 utf-8
'params': 提交的参数,JSON 格式,如{var1:'北京', var2:'test'}
'success': 响应成功时的处理函数,传入参数是标准 XMLHttpRequest 对象
'fail': 请求失败时的处理函数,通常是在页面上给出提示,可以为空
'loading': 等行响应时的加载中函数,通常是在页面上给出提示,可以为空
}
*/
xhr:function(json)
{
//取输入参数,以及赋默认值
var
url=json.url,
method=json.type || 'get',
params=json.params || {},
onComplete=json.success,
charset=json.charset || 'utf8',
onFailure=json.fail,
loading=json.loading;
var getHTTPObject = function() {
var xmlhttp = false;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else if(window.ActiveXObject) {
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
xmlhttp = false;
}
}
}
return xmlhttp;
};
if (loading)
{
loading();
}
var query = '';
for (var i in params)
{
var param = params[i];
if ('gb2312'==charset)
{
param = escape(param);
}
//最终解决 IE 中 GET 方式参数值传递不灵,给 UTF-8 字符集时统一加上 encodeURIComponent
else
{
param = encodeURIComponent(param);
}
query+= i + '='+ param + '&';
}
var XHR = getHTTPObject();
//XHR.setRequestHeader("charset","gb2312");
XHR.onreadystatechange = function() {
if (XHR.readyState == 4) {
if (XHR.status == 200 || XHR.status == 304) {
if (onComplete) {
onComplete(XHR);
}
}
else
{
if (onFailure) {
onFailure(XHR)
};
}
}
};
method = ('get' == method.toLowerCase()) ? 'get':'post';
if ('post'==method)
{
XHR.open(method, url, true);
XHR.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
XHR.send(query);
}
else
{
url += '?'+ query + 'random='+Math.random();
XHR.open(method, url, true);
XHR.send(null);
}
}
}
};
ajax_utf.php
<?php
$test = isset($_GET['test']) ? $_GET['test'] : $_POST['test'];
//要让 IE 正常接收 UTF8 的数据,必须使用大写的“UTF-8”,而不能用小写!
header("text/plain;charset=UTF-8");
echo ($test);
GB2312 变通方案
前后端文件本身统一都用ANSI编码。
HTML 文件使用声明:
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
让 Ajax 对象不以默认的 UTF-8 编码发送数据,核心的变通是把参数值统一用 escape() 处理,汉字会变成 %u5317%u4EAC 这样的 Unicode 格式,从而浏览器会把它们当作西文数据,不再像普通汉字那样用 UTF-8 字符集再进行 URI 编码。即 SF.HTTP.xhr_utf.js 中的如下这行
param = escape(param);
注意此时后台 PHP 程序接收到的请求数据是未编码的 Unicode 格式,需要转回成 GB2312 字符集的数据,使用PHP 程序中的 unescape() 函数即可。输出数据也必须是GB2312编码的,输出前加上声明:
header("Content-type: text/html; charset=gb2312");
SF.HTTP.xhr() 方法使用说明请见方法注释及 HTML 范例。
不同字符集的范例包中 SF.HTTP.xhr.js 和 SF.HTTP.xhr_utf.js 内容完全相同,只是 SF.HTTP.xhr_utf.js 的文件编码是 UTF-8。建议使用 UTF-8 版时把前后全部文件都统一成 UTF-8 编码的文件,因为 IE 浏览器要求引用的外部文件也必须是UTF-8 编码。
以下是各文件完整的代码:
sfxhr.htm
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>AJAX中文-GB2312版</title>
<script type="text/javascript" src="SF.HTTP.xhr.js" mce_src="SF.HTTP.xhr.js"></script>
</head>
<body>
<script type="text/javascript"></script>
</body>
</html>
SF.HTTP.xhr.js
var SF =
{
//HTTP 请求相关
HTTP:
{
/**兼容 GB2312 字符集的 Ajax 调用方法
变通是用 escape,提交的汉字会变成 %u9886%u5730 这样的,后端程序再处理成GB字符集的中文,见 ajax.php 中的 unescape 函数。
输入参数,JSON 格式对象
{
'url': url, 请求的 URL
'type': method, 提交方式,get 或 post,默认为 get
'charset':charset, 字符集,默认 utf-8
'params': 提交的参数,JSON 格式,如{var1:'北京', var2:'test'}
'success': 响应成功时的处理函数,传入参数是标准 XMLHttpRequest 对象
'fail': 请求失败时的处理函数,通常是在页面上给出提示,可以为空
'loading': 等行响应时的加载中函数,通常是在页面上给出提示,可以为空
}
*/
xhr:function(json)
{
//取输入参数,以及赋默认值
var
url=json.url,
method=json.type || 'get',
params=json.params || {},
onComplete=json.success,
charset=json.charset || 'utf8',
onFailure=json.fail,
loading=json.loading;
var getHTTPObject = function() {
var xmlhttp = false;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else if(window.ActiveXObject) {
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
xmlhttp = false;
}
}
}
return xmlhttp;
};
if (loading)
{
loading();
}
var query = '';
for (var i in params)
{
var param = params[i];
if ('gb2312'==charset)
{
param = escape(param);
}
//最终解决 IE 中 GET 方式参数值传递不灵,给 UTF-8 字符集时统一加上 encodeURIComponent
else
{
param = encodeURIComponent(param);
}
query+= i + '='+ param + '&';
}
var XHR = getHTTPObject();
//XHR.setRequestHeader("charset","gb2312");
XHR.onreadystatechange = function() {
if (XHR.readyState == 4) {
if (XHR.status == 200 || XHR.status == 304) {
if (onComplete) {
onComplete(XHR);
}
}
else
{
if (onFailure) {
onFailure(XHR)
};
}
}
};
method = ('get' == method.toLowerCase()) ? 'get':'post';
if ('post'==method)
{
XHR.open(method, url, true);
XHR.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
XHR.send(query);
}
else
{
url += '?'+ query + 'random='+Math.random();
XHR.open(method, url, true);
XHR.send(null);
}
}
}
};
ajax.php
<?php
//如果输入参数不是 unicode 格式的值,则会原样返回。
function unescape($str) {
$str = rawurldecode($str);
preg_match_all("/(?:%u.{4})|&#x.{4};|&#/d+;|.+/U",$str,$r);
$ar = $r[0];
//print_r($ar);
foreach($ar as $k=>$v) {
if(substr($v,0,2) == "%u")
$ar[$k] = iconv("UCS-2","GB2312",pack("H4",substr($v,-4)));
elseif(substr($v,0,3) == "&#x")
$ar[$k] = iconv("UCS-2","GB2312",pack("H4",substr($v,3,-1)));
elseif(substr($v,0,2) == "&#") {
echo substr($v,2,-1)."<br>";
$ar[$k] = iconv("UCS-2","GB2312",pack("n",substr($v,2,-1)));
}
}
return join("",$ar);
}
$test = isset($_GET['test']) ? $_GET['test'] : $_POST['test'];
//为确保输出内容为指定字符集,显式声明一下。要输出 GB2312 字符集内容时,
header("Content-type: text/html; charset=gb2312");
echo unescape($test);
原文链接: https://www.snowpeak.fun/cn/article/detail/solve_garbled_chinese_in_ajax/