Juploader 1.0 谷歌(chrome)浏览器中成功上传文件后返回信息异常

 

在项目中使用了Juploader 1.0无刷新上传文件的js组件,在IE8以上没有问题,代码如下:

function InitialUploadDirectly(OnUploadFunc, buttonID, allowedExts) {
            $.jUploader({
                button: buttonID, // 这里设置按钮id
                eventType: 1, //触发类型   
                addeventbutton: buttonID, // 要绑定事件的元素的id   
                filenamed: buttonID + 'divFileName', //存放选择的文件路径的文本框的id  
                checkMethod: function () { return checkForm(); },
                afterChoose: function (fileName) { afterUpload(fileName, buttonID); },

                allowedExtensions: allowedExts, // 设置允许上传的后缀,当然最好在服务器端也做验证

                // 开始上传事件
                onUpload: function (fileName) {
                    var url = "**.ashx";
                    if (OnUploadFunc != null) {
                        url = OnUploadFunc();
                    }
                    $.jBox.tip("正在上传文件,请稍候!", "loading");
                    return url;
                },

                // 上传完成事件
                onComplete: function (fileName, response) {
                    // response是json对象,格式可以按自己的意愿来定义,例子为: { success: true, fileUrl:'' }
                    console.log(response);
                    if (response.Msg == "success") {
                        AfterUploadCompleteSuccess(response.AddedFile.S_ID, fileName);

                    }
                    else if (response.Msg == "error") {
                        jBox.closeTip();
                        jBox.error("文件大小不能超过50M", "错误提示");
                    }
                    else {
                        jBox.closeTip();
                        jBox.error(response.Msg, "错误提示");
                    }
                },

                // 系统信息显示(例如后缀名不合法)
                showMessage: function (message) {

                    jBox.tip(message, 'error');
                },

                // 取消上传事件
                onCancel: function (fileName) {
                    jBox.tip(fileName + ' 上传取消。', 'info');
                },

                // 自己定义文字
                messages: {
                    upload: '添加附件...',
                    emptyFile: "{file} 为空,请选择一个文件.",
                    invalidExtension: "{file} 后缀名不合法. 只有 {extensions} 是允许的.",
                    onLeave: "文件正在上传,如果你现在离开,上传将会被取消。"
                }
            });
        }

但是使用Chrome(我测试的版本为31)浏览器测试的时候,虽然服务器已经接收到上传的文件,并且返回了json格式的数据对象,但是前台脚本中始终得不到返回值,response始终为{“Msg”:”error”},查看Jquploader的源码,发现response是在complete事件中try catch 中异常情况中赋的值,下面代码中黄色标识的部分

var complete = function () {
            try {
                options.uploading = false;
                $('#jUploader-file' + options.id).show();
                options.button.children('span').text(options.messages.upload);

                var iframe = $('#jUploaderIframe' + options.id).get(0);
                // when we remove iframe from dom
                // the request stops, but in IE load
                // event fires
                if (!iframe.parentNode) {
                    return;
                }

                // fixing Opera 10.53
                if ((iframe.contentDocument &&
                iframe.contentDocument.body &&
                iframe.contentDocument.body.innerHTML == "false")
                || (iframe.contentWindow.document &&
                iframe.contentWindow.document.body &&
                iframe.contentWindow.document.body.innerHTML == "false")) {
                    // In Opera event is fired second time
                    // when body.innerHTML changed from false
                    // to server response approx. after 1 sec
                    // when we upload file with iframe
                    return;
                }



                // iframe.contentWindow.document - for IE<7
                var doc = iframe.contentDocument ? iframe.contentDocument : iframe.contentWindow.document;
                var response;

                log("innerHTML = " + doc.body.innerHTML);

                try {
                    var json = doc.body.innerHTML.replace(/<pre>(.*)<\/pre>/g, '$1');
                    response = eval("(" + json + ")");
                } catch (e) {
                    response = { "Msg": "error" };
                    //throw e;
                }
                console.log(response);
                // timeout added to fix busy state in FF3.6
                setTimeout(function () {
                    $('#jUploaderForm' + options.id).remove();
                    $('#jUploaderIframe' + options.id).remove();
                }, 10);

                options.onComplete(options.fileName, response);
            }
            catch (e) {
                setTimeout(function () {
                    $('#jUploaderForm' + options.id).remove();
                    $('#jUploaderIframe' + options.id).remove();
                }, 10);
                response = { "Msg": "error" };
                options.onComplete(options.fileName, response);
            }
        };

继续调试发现下面这段代码中

var json = doc.body.innerHTML.replace(/<pre>(.*)<\/pre>/g, '$1');的json始终为空,但是实际上后台是返回了值的。

继续查看源码,明白了Juploader的基本思想,是在页面中创建iframe,再在iframe中构建一个form,form的action指向上传文件的后台服务器地址,如下:

$(document.body).append(createIframe()).append(createForm());

并且在iframe的onload事件中绑定自定义的complete方法,如下:

var createIframe = function () {
            var id = 'jUploaderIframe' + options.id;
            var iframe = $('<iframe id="' + id + '" name="' + id + '" src="javascript:false;" style="display:none"></iframe>').bind('load', complete);

            return iframe;
        };

这样在iframe中的form加载完成后会执行iframe的onload事件(具体iframe的onload事件的用法,可自行百度,这里不多做解释了)。

但是在调试过程中却发现onload的事件总是先执行,也就是说complete方法在执行的时候form其实还没有加载完成,以下是控制台日志显示内容:

于是怀疑是因为代码顺序的问题造成的,再看一下具体的代码

createIframe方法中:

var iframe = $('<iframe id="' + id + '" name="' + id + '" src="javascript:false;" style="display:none"></iframe>').bind('load', complete); 

upload方法中:

$(document.body).append(createIframe()).append(createForm());

于是调整代码在iframe append form 后,再bind iframe 的onload事件

createIframe方法中

var iframe = $('<iframe id="' + id + '" name="' + id + '" src="javascript:false;" style="display:none"></iframe>')

去掉了bind  load 的事件

而在upload方法中:

var ifrm = createIframe();
$(document.body).append(ifrm).append(createForm());
ifrm.bind("load", complete);

这样修改之后,上传完成事件onComplete 的response参数就可以正常获取form 中action 页面的回传值了

posted @ 2017-12-09 12:51  八方鱼  阅读(995)  评论(0编辑  收藏  举报