jQuery ajax在GBK编码下表单提交终极解决方案(非二次编码方法)


Posted in Javascript onOctober 20, 2010

前言:
当jquery ajax在utf-8编码下(页面utf-8,接收utf-8),无任何问题。可以正常post、get,处理页面直接获取正确的内容。
但在以下情况下:
GBK -> AJAX POST ->GBK
UTF-8 -> AJAX POST ->GBK
后台代码无法获取正确的内容,通常表现为获取到奇怪字符、问号。
经典解决方法:
1:发送页面、接收页面均采用UTF-8编码。
2:发送页面在调用ajax post方法之前,将含有中文内容的input用encodeURIComponent编码一次,而接收页面则调用解码方法( 如:java.net.urldecoder.decode("接收到内容","utf-8") )。

其中,第一种方法无疑是最简单、最直接,但往往不符合实际,因为很多项目并不是使用utf-8编码,例如国内大部分使用gbk编码,也不可能为了解决这样一个问题,而将整个项目转换为utf-8编码,成本太大,风险太高。
第二方法,是现在最多人使用的方法,俗称二次编码,为什么叫二次编码,等下会解释。客户端编码两次,服务端解码两次。但这种方法不好的地方,就是前台手动编码一次,后台再手动解码一次,稍不留神就会忘记,而且代码掺和前台逻辑。
交互过程:
当我们使用表单按照传统方式post提交时候(非AJAX提交),浏览器会根据当前页面编码,encode一次,然后发送到服务端,服务端接收到表单,会自动dencode一次,通常这个过程是对程序是透明的,因此加上手动编码、解码,就变成上面所说的二次编码。
但当我们使用AJAX方式提交时候,浏览器并不会自动替我们encode,因此在jquery中有这样的一段代码:

ajax: function( s ) { 
// Extend the settings, but re-extend 's' so that it can be 
// checked again later (in the test suite, specifically) 
s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s)); 
var jsonp, jsre = /=?(&|$)/g, status, data, 
type = s.type.toUpperCase(); 
// convert data if not already a string 
if ( s.data && s.processData && typeof s.data !== "string" ) 
s.data = jQuery.param(s.data); 
........ 
}

以上是jquery的ajax方法的代码片段,下面是正常调用jquery ajax post的代码:
$.ajax({ 
url: ajaxurl, 
type: 'POST', 
dataType: 'html', 
timeout: 20000,//超时时间设定 
data:para,//参数设置 
success: function(html){ 
} 
});

通过上面代码可以知道,当设置了data时候,jquery内部会调用jQuery.param方法对参数encode(执行本应浏览器处理的encode)。
jQuery.param=function( a ) { 
var s = [ ]; 
function add( key, value ){ 
s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value); 
}; 
// If an array was passed in, assume that it is an array 
// of form elements 
if ( jQuery.isArray(a) || a.jquery ) 
// Serialize the form elements 
jQuery.each( a, function(){ 
add( this.name, this.value ); 
}); 
// Otherwise, assume that it's an object of key/value pairs 
else 
// Serialize the key/values 
for ( var j in a ) 
// If the value is an array then the key names need to be repeated 
if ( jQuery.isArray(a[j]) ) 
jQuery.each( a[j], function(){ 
add( j, this ); 
}); 
else 
add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] ); 
// Return the resulting serialization 
return s.join("&").replace(/%20/g, "+"); 
}//jquery.param end

解决方法:

encodeURIComponent会以utf-8编码,在gbk编码下,可不可以以gbk进行编码呢?

如果还在打encodeURIComponent主意的话,那不好意思,encodeURIComponent只会utf-8编码,并没有其他api进行其他编码;不过,别担心,看看下面:

encodeURIComponent,它是将中文、韩文等特殊字符转换成utf-8格式的url编码。

escape对0-255以外的unicode值进行编码时输出%u****格式,其它情况下escape,encodeURI,encodeURIComponent编码结果相同。

哈哈,看到希望吧?没错,就是用escape代替encodeURIComponent方法,不过必须注意:

escape不编码字符有69个:*,+,-,.,/,@,_,0-9,a-z,A-Z

encodeURIComponent不编码字符有71个:!, ',(,),*,-,.,_,~,0-9,a-z,A-Z

使用了escape之后必须对加号进行编码,否则,当内容含有加号时候会被服务端翻译为空格。

终于知道解决办法了,重写jquery代码:

jQuery.param=function( a ) { 
var s = [ ]; 
var encode=function(str){ 
str=escape(str); 
str=str.replace(/+/g,"%u002B"); 
return str; 
}; 
function add( key, value ){ 
s[ s.length ] = encode(key) + '=' + encode(value); 
}; 
// If an array was passed in, assume that it is an array 
// of form elements 
if ( jQuery.isArray(a) || a.jquery ) 
// Serialize the form elements 
jQuery.each( a, function(){ 
add( this.name, this.value ); 
}); 
// Otherwise, assume that it's an object of key/value pairs 
else 
// Serialize the key/values 
for ( var j in a ) 
// If the value is an array then the key names need to be repeated 
if ( jQuery.isArray(a[j]) ) 
jQuery.each( a[j], function(){ 
add( j, this ); 
}); 
else 
add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] ); 
// Return the resulting serialization 
return s.join("&").replace(/%20/g, "+"); 
}

上面那段代码并不需要在jquery的源文件重写,可以在你项目的javascript贴上,覆盖它原有的方法,不过必须在jquery加载之后。

经初步验证,上面那段代码在utf-8编码也可以工作正常,大概是编码成unicode的缘故吧。

这样,就不是需要使用什么二次编码,即影响前台,又影响后台。gbk编码下ajax post不再是问题了,此乃是终极解决方法。哈哈。

有兴趣的可以到http://www.open-lib.com/Forum/Read_69_1.action与作者交流。

Javascript 相关文章推荐
类似CSDN图片切换效果脚本
Sep 17 Javascript
深入理解JavaScript系列(13) This? Yes,this!
Jan 18 Javascript
JS调用CS里的带参方法实例
Aug 01 Javascript
基于jquery实现的省市区级联无ajax
Sep 24 Javascript
基于javascript滚动图片具体实现
Nov 18 Javascript
如何给ss bash 写一个 WEB 端查看流量的页面
Mar 23 Javascript
Vue.js实现实例搜索应用功能详细代码
Aug 24 Javascript
微信小程序导航栏跟随滑动效果的实现代码
May 14 Javascript
简单谈谈javascript高级特性
Sep 04 Javascript
layer iframe 设置关闭按钮的方法
Sep 12 Javascript
vue解决使用$http获取数据时报错的问题
Oct 30 Javascript
Vue+Node实现的商城用户管理功能示例
Dec 23 Javascript
关于javascript中this关键字(翻译+自我理解)
Oct 20 #Javascript
javascript动态改变img的src属性图片不显示的解决方法
Oct 20 #Javascript
javascript奇异的arguments分析
Oct 20 #Javascript
超越Jquery_01_isPlainObject分析与重构
Oct 20 #Javascript
理解Javascript_15_作用域分配与变量访问规则,再送个闭包
Oct 20 #Javascript
理解Javascript_14_函数形式参数与arguments
Oct 20 #Javascript
理解Javascript_13_执行模型详解
Oct 20 #Javascript
You might like
php调用mysql存储过程
2007/02/14 PHP
体育彩票排列三组选三算法分享
2014/03/07 PHP
yii操作session实例简介
2014/07/31 PHP
smarty高级特性之过滤器的使用方法
2015/12/25 PHP
简单理解PHP的面向对象编程方式
2016/05/17 PHP
[原创]PHP实现字节数Byte转换为KB、MB、GB、TB的方法
2017/08/31 PHP
ThinkPHP5+UEditor图片上传到阿里云对象存储OSS功能示例
2019/08/05 PHP
PHP const定义常量及global定义全局常量实例解析
2020/05/28 PHP
javascript下给元素添加事件的方法与代码
2007/08/13 Javascript
HTML DOM的nodeType值介绍
2011/03/31 Javascript
jQuery学习总结之元素的相对定位和选择器(持续更新)
2011/04/26 Javascript
jQuery 取值、赋值的基本方法整理
2014/03/31 Javascript
jQuery中serializeArray()与serialize()的区别实例分析
2015/12/09 Javascript
JavaScript入门教程之引用类型
2016/05/04 Javascript
js返回顶部实例分享
2016/12/21 Javascript
使用express搭建一个简单的查询服务器的方法
2018/02/09 Javascript
详解element-ui设置下拉选择切换必填和非必填
2019/06/17 Javascript
Layui 解决表格异步调用后台分页的问题
2019/10/26 Javascript
Vue初始化中的选项合并之initInternalComponent详解
2020/06/11 Javascript
python实现DNS正向查询、反向查询的例子
2014/04/25 Python
django Serializer序列化使用方法详解
2018/10/16 Python
正确理解Python中if __name__ == '__main__'
2019/01/24 Python
python适合人工智能的理由和优势
2019/06/28 Python
python提取log文件内容并画出图表
2019/07/08 Python
python+jinja2实现接口数据批量生成工具
2019/08/28 Python
Python集成开发工具Pycharm的安装和使用详解
2020/03/18 Python
Python爬虫基于lxml解决数据编码乱码问题
2020/07/31 Python
python 获取字典特定值对应的键的实现
2020/09/29 Python
html5 canvas的绘制文本自动换行的示例代码
2018/09/17 HTML / CSS
越南综合购物网站:Lazada越南
2019/06/10 全球购物
物理教育专业求职信
2014/06/25 职场文书
2014年环境卫生工作总结
2014/11/24 职场文书
2014年音乐教师工作总结
2014/12/03 职场文书
创业计划之特色精品店
2019/08/12 职场文书
React 并发功能体验(前端的并发模式)
2021/07/01 Javascript
详解Python中下划线的5种含义
2021/07/15 Python