为什么XMLHttpRequest ProgressEvent.lengthComputable可能为false?

时间:2012-06-08 22:07:46

标签: javascript ajax xmlhttprequest

我正在尝试使用XMLHttpRequest 2级支持进度事件来实现HTML5方式的上传进度条。

在您看到的每个示例中,方法是向progress事件添加事件侦听器,如下所示:

req.addEventListener("progress", function(event) {
    if (event.lengthComputable) {
        var percentComplete = Math.round(event.loaded * 100 / event.total);
        console.log(percentComplete);
    }
}, false);

这些示例似乎总是假设event.lengthComputable将为true。毕竟,浏览器肯定知道它发送的请求的长度吗?

无论我做什么,event.lengthComputable都是false。我已经在Safari 5.1.7和Firefox 12上测试了这两个版本,两者都在OSX上。

我的网站是使用Django构建的,我的开发和生产设置也遇到了同样的问题。

我用来生成表单上传的完整代码如下所示(使用jQuery):

form.submit(function() {
    // Compile the data.
    var data = form.serializeArray();
    data.splice(0, 0, {
        name: "file",
        value: form.find("#id_file").get(0).files[0]
    });
    // Create the form data.
    var fd = new FormData();
    $.each(data, function(_, item) {
        fd.append(item.name, item.value);
    });
    // Submit the data.
    var req = new XMLHttpRequest();
    req.addEventListener("progress", function(event) {
        if (event.lengthComputable) {
            var percentComplete = Math.round(event.loaded * 100 / event.total);
            console.log(percentComplete);
        }
    }, false);
    req.addEventListener("load", function(event) {
        if (req.status == 200) {
            var data = $.parseJSON(event.target.responseText);
            if (data.success) {
                console.log("It worked!")
            } else {
                console.log("It failed!")
            }
        } else {
            console.log("It went really wrong!")
        }
    }, false);
    req.addEventListener("error", function() {
        console.log("It went really really wrong!")
    }, false);
    req.open("POST", "/my-bar/media/add/");
    req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    req.send(fd);
    // Don't really submit!
    return false;
});

我已经把头发撕了好几个小时了。任何帮助表示赞赏!

3 个答案:

答案 0 :(得分:33)

嘿,我从@ComFreek找到了the answer

我犯了同样的错误。

我写的这句话是:

xhr.onprogress = uploadProgress;

正确的应该是

xhr.upload.onprogress = uploadProgress;

答案 1 :(得分:1)

看看这个: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

xhr.upload.addEventListener('progress',function(e){})也可以。

答案 2 :(得分:1)

我也遇到使用AJAX(xmlhttprequest)发送多个大文件的问题。

找到了解决方案,这是我使用的完整脚本。 您只需在HTML页面中放置下一行:

<input type="file" multiple name="file" id="upload_file" onchange="handleFiles(this)">

并使用下一个脚本:

<script type="text/javacript">
    var filesArray;
    function sendFile(file)
    {
        var uri = "<URL TO PHP FILE>";
        var xhr = new XMLHttpRequest();
        var fd = new FormData();

        var self = this;

        xhr.upload.onprogress = updateProgress;
        xhr.addEventListener("load", transferComplete, false);
        xhr.addEventListener("error", transferFailed, false);
        xhr.addEventListener("abort", transferCanceled, false);
        xhr.open("POST", uri, true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4 && xhr.status == 200) {
                alert(xhr.responseText); // handle response.
            }
        };
        fd.append('myFile', file);
        // Initiate a multipart/form-data upload
        xhr.send(fd);
    }
    function updateProgress (oEvent)
    {
        if (oEvent.lengthComputable)
        {
            var percentComplete = oEvent.loaded / oEvent.total;
            console.log(Math.round(percentComplete*100) + "%");
        } else {
            // Unable to compute progress information since the total size is unknown
            console.log("Total size is unknown...");
        }
    }

    function transferComplete(evt)
    {
        alert("The transfer is complete.");
    }

    function transferFailed(evt)
    {
        alert("An error occurred while transferring the file.");
    }

    function transferCanceled(evt)
    {
        alert("The transfer has been canceled by the user.");
    }
    function handleFiles(element)
    {
        filesArray = element.files;
        if (filesArray.length > 0)
        {
            for (var i=0; i<filesArray.length; i++)
            {
                sendFile(filesArray[i]);
            }
            filesArray = '';
        }
    }
    </script>

您的结果将在控制台中