-
2009-09-08
ajax提交的乱码问题 - [javascript]
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://www.my1px.cn/logs/45994312.html
一向写html都是用的utf-8,现在却要用GB的,在做ajax请求的时候,java程序员说我提交过去的都是乱码....晕....
后来问清羽师父(顺便夸一下我师父,是个性格内敛,办事有条理,个性很好的人^_^,在TB,平日里,七七八八的问题都多亏了他了。我觉得他很厉害,只是不爱表现...),通过ajax请求地址后面加?_input_charset=utf-8解决了问题,原来开发那个有个框架会根据这个参数自动处理。和和,差点急死,开发那边居然要求我把传过去的数据转变编码,我晕死!
问题是解决了,可问题怎么来的呢?
百度了一下编码的知识:(以下引用自51goodhome的空间)
1、编码
编码比较常用的有: UTF-8, GBK, GB2312, ISO-8859-1,除了 iso-8859-1之外的其它三个编码都能很好的支持中文,但它们都兼容 ISO-8859-1的编码(就是说无论编码怎么改变,只要是 ISO-8859-1中的字符,永远不会出现乱码)。
这四种编码中, GB2312是中国规定的汉字编码,也可以说是简体中文的字符集编码;GBK 是 GB2312的扩展 ,除了兼容GB2312外,它还能显示繁体中文,还有日文的假名;而 UTF-8虽然也支持中文,但却与GB码不兼容(编码值不同)。UTF-8使用的是可变长的 UNICODE编码,编码可能是 1位 16进制(即 ISO-8859-1中的字符,其编码也是相同的)也有可能是 2位或 3位的 16进制。 UTF-8的优点是:1、与CPU字节顺序无关 , 可以在不同平台之间交流。 2、容错能力高 , 任何一个字节损坏后 , 最多只会导致一个编码码位损失 , 不会链锁错误 (如 GB码错一个字节就会整行乱码 ),所以在国际化处理中基本都是建议使用 UTF-8作为编码。2、文件的编码
文件编码最常使用的有两种:ANSI和UTF-8,光看名字估计你都可以猜到了,ANSI就是我们保存文件时使用的默认编码,而UTF-8则需自己设置。对于编码的改变,我使用的工具是NOTEPAD和ECLIPSE,NOTEPAD使用最简单,只要打开文件后在另存为中选择相应的编码就行了,而且它对编码的支持非常好;而在ECLIPSE中,只要稍微设置一下就行了,打开首选项,然后选择:常规->内容类型(ContentType),在右边选中你想改变保存编码的文件类型,然后在下方的缺省编码中改变其值,最后点击更新(UPDATE)按钮即可。
而在其它的编辑器中,默认保存的内容都是GB2312或者GBK(NOTEPAD中对应ANSI).而根据前面所说的UTF-8和GBK,GB2312等 的编码值是不同的这一点,可以知道,如果文件使用了UTF-8,那么字符编码就必须使用UTF-8,否则编码值的不同就可能造成乱码。而这也就是为什么那 么多的人使用了UTF-8编码后还会产生乱码的根本原因。(JS和JSP都是这个道理)另外,还附了一个解决ajax里乱码的方法:
6、AJAX提交数据乱码,返回数据乱码的解决方案
万变不离其宗,AJAX的乱码问题自然跟编码有关了,其实很多人跟我一样想到了对文件编码进行设置,并且在接数据时设置了requet的编码,在返回的数 据时设置了response的编码一切都以为会很顺利,可是这一切都是徒劳无功的,讨厌的乱码再一次出现在你眼前。在你试了N多种方法,包括JS自身的 escape,unescape方法后,你发现乱码仍然猖狂地出现在屏幕上。
其实在试过这N多方法后,很多人都没发现,解决的方法其实很简单,而且其答案就在我们之前处理的JSP乱码之中。让我们先看一下AJAX的经典请求代码xmlhttp.open( "post", url, async );
xmlhttp.setRequestHeader( "Content-Type", "text/html" );
xmlhttp.send( params );通过前面的说明,不知道你现在看出端倪了没有。不知道是受了网上教程的影响还是其它方面影响,setRequestHeader并是万年不变的,也没人想过去改它,而问题就正好出在这个地方。回想一个JSP页面内容的编码设置,其中有这么一节:
contentType="text/html; charset=UTF-8"
现在知道问题了吧,所以我们要把第二句代码改为:
xmlhttp.setRequestHeader( "Content-Type", "text/html;charset=UTF-8" );
如果提交的是form,那么设置为"application/x-www-form-urlencoded; charset=UTF-8"
最后别忘了在返回数据时也设置上:
response.setContentType( "text/xml" );
response.setCharacterEncoding( "UTF-8" );如果要问为什么的话,其实我们可以把xmlhttp看成是一个临时页面,它由浏览 器动态生成,主要作用是在后台获得请求的数据(可以看成是一个高级的iframe)。所以对于普通页面设置的编码,对它也要同样设置。而在servlet 中返回数据为什么要设置contentType和encoding其道理也是一样的。众所周知,jsp的最后形态就是servlet,而jsp页首设置的 那个内容其实也就是让生成的servlet中生成这么两句话:
response.setContentType( "text/html" );
response.setCharacterEncoding( "UTF-8" );而pageEncoding则是跟jvm说明了这个页面的内容要使用什么编码保存(这跟之后生成的CLASS有关系)。所以在servlet设置response的编码也是理所当然的了。
response.setContentType("text/xml;charset=UTF-8");
response.setHeader("Pragma", "no-cache"); //HTTP 1.0
response.setDateHeader("Expires", 0); //prevents caching at the proxy server
PrintWriter out = response.getWriter();
out.write(outXML);
out.flush();
out.close();
OK!这样向客户端写的数据中的中文也是UTF-8编码了,客户端js脚本获取到request.responseXML也好,responseText也好,里面的数据都不会有乱码了
=====================================================================================
OK,yui是不是也是这么处理的呢?我翻了一下connection-debug,发现在用post方法时,用initHeader定义了Content-Type,但值是'application/x-www-form-urlencoded; charset=UTF-8',如果是传文件(uploadFile)就是'multipart/form-data',而不是'text/xml;charset=UTF-8'.application/x-www-form-urlencoded我一般看都是写在form表单上的,到底干什么用的,汗死。goooooooooooooogle:表单元素的enctype属性指定的是表单数据的编码方式,该属性有3个值:
1) application/x-www-form-urlencoded:这是默认编码方式,它只处理表单域里的value属性值,采用这种编码方式的表单会将表单域的值处理成URL编码方式。
2) multipart/form-data:这种编码方式的表单会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到
请求参数里。
3) text/plain:这种方式主要适用于直接通过表单发送邮件的方式。
文件上传是web应用经常用到的一个知识。原理是,通过为表单元素设置enctype=”multipart/form-data”属性,让表单提交的数据以二
进制编码的方式提交,在接收此请求的Servlet中用二进制流来获取内容,就可以取得上传文件的内容,从而实现文件的上传。
当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1& amp;name2=value2...),然后把这个字串append到url后面,用?分割,加载这个新的url。
当action为post时候,浏览器把form数据封装到http body中,然后发送到server。
如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。
但 是如果有type=file的话,就要用到multipart/form-data了。浏览器会把整个表单以控件为单位分割,并为每个部分加上 Content-Disposition(form-data或者file),Content-Type(默认为text/plain),name(控件 name)等信息,并加上分割符(boundary)。如果有以下form,并选择了file1.txt上传
<form action="http://server.com/cgi/handle"
enctype="multipart/form-data"
method="post">
<input type="text" name="submit-name" value="chmod777"><br />
What files are you sending? <input type="file" name="files"><br />
</form>
则有如下body:
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
chmod777
--AaB03x
Content-Disposition: form-data; name="files"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
看来就是指ajax提交过去post数据的方式?
收藏到:Del.icio.us







