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 相关文章推荐
CSS+JS构建的图片查看器
Jul 22 Javascript
深入理解JavaScript系列(14) 作用域链介绍(Scope Chain)
Apr 12 Javascript
jQuery实现在列表的首行添加数据
May 19 Javascript
Web打印解决方案之普通报表打印功能
Aug 29 Javascript
js实现文字超出部分用省略号代替实例代码
Sep 01 Javascript
JS使用正则截取两个字符串之间的字符串实现方法详解
Jan 06 Javascript
详解微信小程序入门五: wxml文件引用、模版、生命周期
Jan 20 Javascript
关于AngularJs数据的本地存储详解
Jan 20 Javascript
详谈js原型继承的一些问题
Sep 06 Javascript
小试SVG之新手小白入门教程
Jan 08 Javascript
Vuex mutitons和actions初使用详解
Mar 04 Javascript
JS桶排序的简单理解与实现方法示例
Nov 25 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
example2.php
2006/10/09 PHP
PHP魔术方法使用方法汇总
2016/02/14 PHP
CI框架实现框架前后端分离的方法详解
2016/12/30 PHP
PHP三种方式实现链式操作详解
2017/01/21 PHP
swoole和websocket简单聊天室开发
2017/11/18 PHP
php生成复杂验证码(倾斜,正弦干扰线,黏贴,旋转)
2018/03/12 PHP
thinkPHP3.2.2框架行为扩展及demo示例
2018/06/19 PHP
CL vs ForZe BO5 第三场 2.13
2021/03/10 DOTA
greybox——不开新窗口看新的网页
2007/02/20 Javascript
基于jQuery的图片剪切插件
2011/08/03 Javascript
js 数组操作之pop,push,unshift,splice,shift
2014/01/29 Javascript
深入理解JavaScript系列(25):设计模式之单例模式详解
2015/03/03 Javascript
jQuery插件开发的五种形态小结
2015/03/04 Javascript
js获取页面及个元素高度、宽度的代码
2016/04/26 Javascript
JavaScript使用正则表达式获取全部分组内容的方法示例
2017/01/17 Javascript
关于javascript sort()排序你可能忽略的一点理解
2017/07/18 Javascript
Vue 进入/离开动画效果
2017/12/26 Javascript
利用Vue2.x开发实现JSON树的方法
2018/01/04 Javascript
纯JS实现的读取excel文件内容功能示例【支持所有浏览器】
2018/06/23 Javascript
Python运维之获取系统CPU信息的实现方法
2018/06/11 Python
Python参数解析模块sys、getopt、argparse使用与对比分析
2019/04/02 Python
使用Python刷淘宝喵币(低阶入门版)
2019/10/30 Python
python speech模块的使用方法
2020/09/09 Python
法国二手手袋、手表和奢侈珠宝购物网站:Collector Square
2018/07/05 全球购物
美国正宗奢华复古手袋、珠宝及配饰网站:What Goes Around Comes Around
2018/07/21 全球购物
blueseventy官网:铁人三项和比赛泳衣
2021/02/06 全球购物
某某同志考察材料
2014/05/28 职场文书
大学活动总结模板
2014/07/10 职场文书
城管执法人员个人对照检查材料思想汇报
2014/09/29 职场文书
主持人大赛开场白
2015/05/29 职场文书
2016年暑期见闻作文
2015/11/25 职场文书
英语版自我评价,35句话轻松搞定
2019/10/08 职场文书
关于拾金不昧的感谢信(五篇)
2019/10/18 职场文书
利用python调用摄像头的实例分析
2021/06/07 Python
python flappy bird小游戏分步实现流程
2022/02/15 Python
浅析Python OpenCV三种滤镜效果
2022/04/11 Python