zoukankan      html  css  js  c++  java
  • 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 页面的回传值了

  • 相关阅读:
    ASP中使用事务控制
    C语言学习笔记——两个数交换位置的多种方式
    PHP字符串函数
    PHP笔记——文件处理
    算法——穿越沙漠算法
    C学习笔记——使用CL编译器
    Wordpress——一些内部参数记录
    C语言笔记——原码、反码、补码
    C学习笔记——内存
    Linux VI编辑器命令集合
  • 原文地址:https://www.cnblogs.com/bayu/p/8011190.html
Copyright © 2011-2022 走看看