Ext2.0的Form乱码问题已经被javaeye炒了n次,但是每次都没有适合自己的方法,最主要的是我的系统是基于GBK编码的,因此很多基于UTF-8的修改意见是没有用的
先总结一下JAVAEYE提供的解决方案,这里主要讲述客户端,服务端无非是encode或者设置filter
1,前后台所有文件统一用UTF-8编码,数据库中最后也用UTF-8编码
点评:这种方法明显只适用于新系统,对于旧系统,这个MS毫无办法,例如我现在用的这个GBK下的系统
2,在Ext中可以修改Request Header中Content-Type的设置,具体的方法为:Ext.lib.Ajax.defaultPostHeader += ";charset=utf-8";
点评:这种方法和上方法道理一致,但是好像还是对我这种系统免疫,即时我在charset里面加了charset=gbk,囧
3,Ext.Ajax.request({
url:'',
params:{
items:encode(Ext.util.JSON.encode(items)) //就是将字符串编码一下
},
method:"POST",
success:function(){alert("成功")}
});
点评:这种方法和我现在的解决思路一致,但是,如果用户是使用Form提交呢?
4,提交前遍历Form的fields,将每个fields的rawValue都encodeURIComponent两次
点评:这种方法也和我现在的解决思路一致,但是,用户提交的一瞬间会看到N多乱码 @@
综上所述,主流的解决办法有2种,一个是用统一的文件编码格式通讯,一个是先统一格式(encodeURIComponent两次),在进行通讯
显而易见,在非UTF-8下解决FORM的乱码提交,必须在一个隐蔽的地方悄悄地吧value给encodeURIComponent两次 :P
从类的继承和调用类关系上,我们可以整理下面这个关系
FormPanel-(extend)->BasicForm-(call)->Action-(call)->Ajax 其中关键部分的代码贴这里,我们要做的悄悄地的encodeURIComponent两次必然是写在这里
BasicForm的
doAction : function(action, options){
if(typeof action == 'string'){
action = new Ext.form.Action.ACTION_TYPES[action](this, options);//调用Action,没机会修改value..
}
if(this.fireEvent('beforeaction', this, action) !== false){
this.beforeAction(action);
action.run.defer(100, action);
}
return this;
},
/**
* Shortcut to do a submit action.
* @param {Object} options The options to pass to the action (see {@link #doAction} for details)
* @return {BasicForm} this
*/
submit : function(options){
if(this.standardSubmit){
var v = this.isValid();
if(v){
this.el.dom.submit();
}
return v;
}
this.doAction('submit', options);
return this;
},
Action的
// private
getParams : function(){
var bp = this.form.baseParams;
var p = this.options.params;
//我将bp和p打印了,这些都不是form的fields,好像是自定义的参数
if(p){
if(typeof p == "object"){
p = Ext.urlEncode(Ext.applyIf(p, bp));
}else if(typeof p == 'string' && bp){
p += '&' + Ext.urlEncode(bp);
}
}else if(bp){
p = Ext.urlEncode(bp);
}
return p;
},
run : function(){
var o = this.options;
var method = this.getMethod();
var isGet = method == 'GET';
if(o.clientValidation === false || this.form.isValid()){
Ext.Ajax.request(Ext.apply(this.createCallback(o), {
form:this.form.el.dom,
url:this.getUrl(isGet),
method: method,
headers: o.headers,
params:!isGet ? this.getParams() : null,//一开始以为是这里处理fields
isUpload: this.form.fileUpload
}));
}else if (o.clientValidation !== false){ // client validation failed
this.failureType = Ext.form.Action.CLIENT_INVALID;
this.form.afterAction(this, false);
}
},
.
Ajax...千呼万唤始出来...就是你了...因为这个已经是ext-base.js里面的对象了,再往上找就没人传数据了...
serializeForm : function(form) {
if(typeof form == 'string') {
form = (document.getElementById(form) || document.forms[form]);
}
var el, name, val, disabled, data = '', hasSubmit = false;
for (var i = 0; i < form.elements.length; i++) {
el = form.elements[i];
disabled = form.elements[i].disabled;
name = form.elements[i].name;
val = form.elements[i].value;
if (!disabled && name){
switch (el.type)
{
case 'select-one':
case 'select-multiple':
for (var j = 0; j < el.options.length; j++) {
if (el.options[j].selected) {
if (Ext.isIE) {
data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
}
else {
data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
}
}
}
break;
case 'radio':
case 'checkbox':
if (el.checked) {
data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
}
break;
case 'file':
case undefined:
case 'reset':
case 'button':
break;
case 'submit':
if(hasSubmit == false) {
data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
hasSubmit = true;
}
break;
default:
data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
break;
}
}
}
data = data.substr(0, data.length - 1);
return data;
},
里面做了一个switch处理,仔细一看,那些case的处理和textinput一点关系都没有,因此,直接修改
default:
data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
成
default:
data += encodeURIComponent(name) + '=' + encodeURIComponent(encodeURIComponent(val)) + '&';
问题终于解决了!
备注:
1,如果谁用了出问题,请联系我的
2,如果设置fileUpload:true,也可以解决乱码问题
在BasicForm中
/**
* @cfg {Boolean} fileUpload.
* Set to true if this form is a file upload.
* <p>File uploads are not performed using normal "Ajax" techniques, that is they are <b>not</b>
* performed using XMLHttpRequests. Instead the form is submitted in the standard manner with the
* DOM <tt><form></tt> element temporarily modified to have its
* {@link http://www.w3.org/TR/REC-html40/present/frames.html#adef-target target} set to refer
* to a dynamically generated, hidden <tt><iframe></tt> which is inserted into the document
* but removed after the return data has been gathered.</p>
* <p>The server response is parsed by the browser to create the document for the IFRAME. If the
* server is using JSON to send the return object, then the
* {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17 Content-Type} header
* must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.</p>
* <p>The response text is retrieved from the document, and a fake XMLHttpRequest object
* is created containing a <tt>responseText</tt> property in order to conform to the
* requirements of event handlers and callbacks.</p>
* <p>Be aware that file upload packets are sent with the content type {@link http://www.faqs.org/rfcs/rfc2388.html multipart/form}
* and some server technologies (notably JEE) may require some custom processing in order to
* retrieve parameter names and parameter values from the packet content.</p>
*/
/**