精华帖 (0) :: 良好帖 (6) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-10-18
最后修改:2010-10-18
[版权声明]:版权归作者所有,转载时请以超链接形式标明文章原始出处和作者信息及本声明: 前言: 当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") )。
第二方法,是现在最多人使用的方法,俗称二次编码,为什么叫二次编码,等下会解释。客户端编码两次,服务端解码两次。但这种方法不好的地方,就是前台手动编码一次,后台再手动解码一次,稍不留神就会忘记,而且代码掺和前台逻辑。 交互过程: 当我们使用表单按照传统方式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
上面是jQuery.param的代码,细心点可以留意到encodeURIComponent这方法,这是javascript内置的方法,对目标字符串执行utf-8 encode,因此,当页面使用gbk编码时候,服务端会使用gbk进行解码,但实际提交的数据是以utf-8编码的,所以造成接收到内容为乱码或者为问号。 解决方法: 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与作者交流。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-10-19
不错,我收下了,下次再遇到类似问题用用看
|
|
返回顶楼 | |
发表时间:2010-10-19
那么少人....
|
|
返回顶楼 | |
发表时间:2010-10-24
引用
定义和用法
escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串。 语法 escape(string)参数 描述 string 必需。要被转义或编码的字符串。 返回值 已编码的 string 的副本。其中某些字符被替换成了十六进制的转义序列。 说明 该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。其他所有的字符都会被转义序列替换。 提示和注释 提示:可以使用 unescape() 对 escape() 编码的字符串进行解码。 注释:ECMAScript v3 反对使用该方法,应用使用 decodeURI() 和 decodeURIComponent() 替代它。
|
|
返回顶楼 | |
发表时间:2010-10-25
magicyz 写道
引用
定义和用法
escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串。 语法 escape(string)参数 描述 string 必需。要被转义或编码的字符串。 返回值 已编码的 string 的副本。其中某些字符被替换成了十六进制的转义序列。 说明 该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。其他所有的字符都会被转义序列替换。 提示和注释 提示:可以使用 unescape() 对 escape() 编码的字符串进行解码。 注释:ECMAScript v3 反对使用该方法,应用使用 decodeURI() 和 decodeURIComponent() 替代它。
但在gbk下,decodeURIComponent和encode的都是以utf-8方式去encode和dencode的,这样得不到正确的数据。 所以才有这样一个方法。。。
|
|
返回顶楼 | |
发表时间:2010-10-25
重写jquery代码这样就对于别人一今后别人使用带来不便。应为别人根本不知道是谁修改的。
|
|
返回顶楼 | |
发表时间:2010-10-25
最后修改:2010-10-25
这个方法,好像只会在ajax才会调用。
而utf-8下也可以post正常。 不过我的项目,是二次封装ajax的,有个变量判断是否需要gbk post,否则还是须由的utf-8 encode。 其实也有个办法,就是不用jq的ajax,自定义一套。 |
|
返回顶楼 | |
发表时间:2010-10-26
你测过吗?我过滤器加编码gbk测试未成功
|
|
返回顶楼 | |
发表时间:2010-10-26
to ls,
你是用了我这方法还是没用? 用了这方法,就是跟平时表单直接post一样,没有分别。 |
|
返回顶楼 | |
发表时间:2010-10-26
smildlzj 写道 to ls,
你是用了我这方法还是没用? 用了这方法,就是跟平时表单直接post一样,没有分别。 var param = [ { name: 'page', value: p.newp } , { name: 'rp', value: p.rp } , { name: 'sortname', value: p.sortname } , { name: 'sortorder', value: p.sortorder } , { name: 'query', value: p.query } , { name: 'qtype', value: p.qtype } , { name: 'qop', value: p.qop } , { name: 'querySql', value: p.querySql } ]; //param = jQuery.extend(param, p.extParam); if (p.extParam) { for (var pi = 0; pi < p.extParam.length; pi++) param[param.length] = p.extParam[pi]; } $.ajax({ type: p.method, url: p.url, data: param, dataType: p.dataType, success: function(data) { if (data != null && data.error != null) { if (p.onError) { p.onError(data); g.hideLoading(); } } else { g.addData(data); } }, error: function(data) { try { if (p.onError) { p.onError(data); } else { alert("获取数据发生异常;") } g.hideLoading(); } catch (e) { } } }); p.method是post,不应该有问题啊? |
|
返回顶楼 | |