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 相关文章推荐
Jquey拖拽控件Draggable使用方法(asp.net环境)
Sep 28 Javascript
capacityFixed 基于jquery的类似于新浪微博新消息提示的定位框
May 24 Javascript
javascript检测是否联网的实现代码
Sep 28 Javascript
Javascript中Array.prototype.map()详解
Oct 22 Javascript
浅谈 javascript 事件处理
Jan 04 Javascript
JavaScript学习笔记之JS事件对象
Jan 22 Javascript
js实现登陆遮罩效果的方法
Jul 28 Javascript
jquery实现未经美化的简洁TAB菜单效果
Aug 28 Javascript
jQuery实现简单隔行变色的方法
Feb 20 Javascript
使用vue.js制作分页组件
Jun 27 Javascript
通过JS和PHP两种方法判断用户请求时使用的浏览器类型
Sep 01 Javascript
angularjs过滤器--filter与ng-repeat配合有奇效
Apr 20 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
点评山进PR-D3L三波段收音机
2021/03/02 无线电
PHP程序员最常犯的11个MySQL错误小结
2010/11/20 PHP
做了CDN获取用户真实IP的函数代码(PHP与Asp设置方式)
2013/04/13 PHP
全面解析PHP面向对象的三大特征
2017/06/10 PHP
thinkphp分页集成实例
2017/07/24 PHP
一款JavaScript压缩工具:X2JSCompactor
2007/06/13 Javascript
javascript 面向对象全新理练之原型继承
2009/12/03 Javascript
ASP.NET jQuery 实例16 通过控件CustomValidator验证RadioButtonList
2012/02/03 Javascript
基于JQuery的类似新浪微博展示信息效果的代码
2012/07/23 Javascript
『jQuery』.html(),.text()和.val()的概述及使用
2013/04/22 Javascript
Javascript中的五种数据类型详解
2014/12/26 Javascript
js实现的Easy Tabs选项卡用法实例
2015/09/06 Javascript
jquery UI Datepicker时间控件的使用方法(基础版)
2015/11/07 Javascript
js实现搜索框关键字智能匹配代码
2020/03/26 Javascript
在Vue methods中调用filters里的过滤器实例
2018/08/30 Javascript
Vue官方推荐AJAX组件axios.js使用方法详解与API
2018/10/09 Javascript
利用JS响应式修改vue实现页面的input值
2019/09/02 Javascript
JavaScript 自定义html元素鼠标右键菜单功能
2019/12/02 Javascript
Nuxt v-bind绑定img src不显示的解决
2019/12/05 Javascript
js判断鼠标移入移出方向的方法
2020/06/24 Javascript
解决vue做详情页跳转的时候使用created方法 数据不会更新问题
2020/07/24 Javascript
Python中列表、字典、元组、集合数据结构整理
2014/11/20 Python
Python注释详解
2016/06/01 Python
用Python实现将一张图片分成9宫格的示例
2019/07/05 Python
学习和使用python的13个理由
2019/07/30 Python
Python itertools.product方法代码实例
2020/03/27 Python
解决python图像处理图像赋值后变为白色的问题
2020/06/04 Python
BudgetAir印度:预订航班、酒店和汽车租赁
2019/07/07 全球购物
日期和时间问题
2015/01/04 面试题
保安自我鉴定范文
2013/12/08 职场文书
薪酬专员岗位职责
2014/02/18 职场文书
大学生精神文明先进个人事迹材料
2014/05/02 职场文书
市场营销计划书范文
2015/01/16 职场文书
秦始皇兵马俑导游词
2015/02/02 职场文书
关于使用Redisson订阅数问题
2022/01/18 Redis
十大最帅动漫男主 碓冰拓海上榜,第一是《灌篮高手》男主角
2022/03/18 日漫