Contents

由于form上传文件(enctype=”multipart/form-data”)不支持Ajax, dwz的解决思路是创建一个不可见的frame(style=”display:none”),上传后把返回的json结果从iframe中提取出来(response = $iframe.contents().find(“body”).html();)转换成json(response = jQuery.parseJSON(response);),再交给callback处理(navTabAjaxDone、dialogAjaxDone等)。

文章来源 www.kowen.cn

查看dwz.ajax.js的代码,处理上传主要是以下两个函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**
* 带文件上传的ajax表单提交
* @param {Object} form
* @param {Object} callback
*/
function iframeCallback(form, callback){
var $form = $(form), $iframe = $("#callbackframe");
if(!$form.valid()) {return false;}
if ($iframe.size() == 0) {
$iframe = $("<iframe id='callbackframe' name='callbackframe' src='about:blank' style='display:none'></iframe>").appendTo("body");
}
if(!form.ajax) {
$form.append('<input type="hidden" name="ajax" value="1" />');
}
form.target = "callbackframe";
_iframeResponse($iframe[0], callback || DWZ.ajaxDone);
}
function _iframeResponse(iframe, callback){
var $iframe = $(iframe), $document = $(document);
$document.trigger("ajaxStart");
$iframe.bind("load", function(event){
$iframe.unbind("load");
$document.trigger("ajaxStop");
if (iframe.src == "javascript:'%3Chtml%3E%3C/html%3E';" || // For Safari
iframe.src == "javascript:'<html></html>';") { // For FF, IE
return;
}
var doc = iframe.contentDocument || iframe.document;
// fixing Opera 9.26,10.00
if (doc.readyState && doc.readyState != 'complete') return;
// fixing Opera 9.64
if (doc.body && doc.body.innerHTML == "false") return;
var response;
if (doc.XMLDocument) {
// response is a xml document Internet Explorer property
response = doc.XMLDocument;
} else if (doc.body){
try{
response = $iframe.contents().find("body").html();
response = jQuery.parseJSON(response);
} catch (e){ // response is html document or plain text
response = doc.body.innerHTML;
}
} else {
// response is a xml document
response = doc;
}
callback(response);
});
}

但在使用chrome开发(版本47)时,返回的结果不是按照正常的statusCode、message、callbackType结构被解析出来执行,而是直接把返回结果原封不动显示了出来。

使用调试工具可以看出这个过程:

当执行到iframeCallback函数最后一行时,iframe中的body还是空的,如下图。

当执行到_iframeResponse函数的 $iframe.bind(“load”, function(event){ 这一行时,body里面已经有了返回的json结果,但是外层包上了pre标签,如下图:

这说明chrome把返回的json结果填入iframe时,会给json外层嵌套一个pre标签,这样_iframeResponse把pre标签的内容转换json出错,捕获异常后就执行了response = doc.body.innerHTML, 把iframe标签的内容直接塞到response里面去了。

解决方法就是修改获取response的方法,把body改为pre,即:response = $iframe.contents().find(“pre”).html()。

仅限于chrome浏览器,其他浏览器下是否存在此问题和解决方法不清楚。

Contents