最近在修改一个ext项目的时候,客户端用ext的上传文件功能,然后服务器返回一段json,我是想返回一段包含html的代码,但无奈每次提交就返回js错误,报错是出现在ext 进行eval那个地方。经过反复试验,发现只要返回字符中包含/ ,例如 json_encode(array('success'=>true,'html'=>'<div>数据</div>')); 那就会报错,当时我真是十分纳闷,以为firebug查看post后返回的数据也没什么异常,为什么就报错呢?
于是我从ext的eval报错的地方入手,一下就发现了问题所在,eval(code);code的内容居然变成了{'success':'true','html':'<div>数据<\/div>'}</div> ,原来后面多了个</div>怪不得怎么也eval不成功,但我返回的数据根本没多出后面的"</div>"啊.只能再一步步跟踪,这个code来源于ext-all-debug.js的6500多行的doFormUpload方法,正是实现上传的过程
doFormUpload : function(o, ps, url){ var id = Ext.id(); var frame = document.createElement('iframe'); frame.id = id; frame.name = id; frame.className = 'x-hidden'; if(Ext.isIE){ frame.src = Ext.SSL_SECURE_URL; } document.body.appendChild(frame); if(Ext.isIE){ document.frames[id].name = id; } var form = Ext.getDom(o.form), buf = { target: form.target, method: form.method, encoding: form.encoding, enctype: form.enctype, action: form.action }; form.target = id; form.method = 'POST'; form.enctype = form.encoding = 'multipart/form-data'; if(url){ form.action = url; } var hiddens, hd; if(ps){ // add dynamic params hiddens = []; ps = Ext.urlDecode(ps, false); for(var k in ps){ if(ps.hasOwnProperty(k)){ hd = document.createElement('input'); hd.type = 'hidden'; hd.name = k; hd.value = ps[k]; form.appendChild(hd); hiddens.push(hd); } } } function cb(){ var r = { // bogus response object responseText : '', responseXML : null }; r.argument = o ? o.argument : null; try { // var doc; if(Ext.isIE){ doc = frame.contentWindow.document; }else { doc = (frame.contentDocument || window.frames[id].document); } if(doc && doc.body){ r.responseText = doc.body.innerHTML; } if(doc && doc.XMLDocument){ r.responseXML = doc.XMLDocument; }else { r.responseXML = doc; } } catch(e) { // ignore } Ext.EventManager.removeListener(frame, 'load', cb, this); this.fireEvent("requestcomplete", this, r, o); Ext.callback(o.success, o.scope, [r, o]); Ext.callback(o.callback, o.scope, [o, true, r]); setTimeout(function(){Ext.removeNode(frame);}, 100); } Ext.EventManager.on(frame, 'load', cb, this); form.submit(); form.target = buf.target; form.method = buf.method; form.enctype = buf.enctype; form.encoding = buf.encoding; form.action = buf.action; if(hiddens){ // remove dynamic params for(var i = 0, len = hiddens.length; i < len; i++){ Ext.removeNode(hiddens[i]); } } }
从代码里看出来,上传过程是先创建一个iframe,然后iframe里动态创建表单,并提交到服务器,服务器返回的内容自然就成了这个iframe的html内容了,所以下面用
body.innerHTML这样的方法来获取返回结果,用firebug一查看,发现body.innerHTML的却变成了{'success':'true','html':'<div>数据<\/div>'}</div>,难道是dom自己做的处理?原来是因为</div>被json_encode变成了<\/div>导致dom认为前面的这个<div>并没有闭合,不能配对,dom就会聪明的在后面给我们补全,导致我们的数据莫名其妙的多出了一些东西。
解决方法,json_encode后,我们把\/转义再还原回来,变成 / 就可以了。