咸鱼的翻身技术

JAVA/JAVASCRIPT

[Ext]Ext2.0的Form乱码问题

  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(thisfalse);
        }
    },
    .

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>&lt;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>&lt;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>
     
*/
    
/**

posted on 2008-07-15 14:42 hopesfish 阅读(2712) 评论(3)  编辑 收藏 引用 所属分类: javascript

Feedback

# re: [Ext]Ext2.0的Form乱码问题 2009-02-13 12:47 请输入你的姓名

不错很详细  回复  更多评论   

# re: [Ext]Ext2.0的Form乱码问题 2009-03-20 09:18 igrrrrrr

很感谢你的方法,我解决好的,乱码问题
另外补充一点
在服务器端取数据的时候应该使用类似一下方法:
String oldname=URLDecoder.decode(httpServletRequest.getParameter("oldname"),"utf-8");
进行解码
  回复  更多评论   

# re: [Ext]Ext2.0的Form乱码问题 2009-03-20 12:50 hopesfish

@igrrrrrr
我们的后端使用struts,用过滤器把你这个实现了:P不然每个属性都要这样,多可怕啊
  回复  更多评论   


只有注册用户登录后才能发表评论。