【问题标题】:JS ProgressEvent is only fired when finishedJS ProgressEvent 仅在完成时触发
【发布时间】:2013-03-07 20:23:11
【问题描述】:

我在让上传进度条正常工作时遇到一些问题。

根据 XMLHttpRequest Level 2 规范,我为 loadstart 和进度附加了事件侦听器,如下所示:

var xhr = $.ajaxSettings.xhr();
xhr.upload.addEventListener('loadstart', function(e) {progressCallback(0);});
xhr.upload.addEventListener('progress', function (e) {
    progressCallback(e.loaded / e.total);
});    

$.ajax({
    url: url,
    type: 'POST',
    processData: false,
    contentType: false,
    data: formData,
    xhr: function () {
        return xhr;
    }
}).done(function (data) {
    // Finish stuff
})

文件已正确上传,但只有在请求以 100% (e.total == e.loaded) 完成后才会调用进度侦听器

上面的代码有什么问题还是需要用什么特殊的方式来配置服务器?

【问题讨论】:

    标签: javascript jquery upload progress xmlhttprequest-level2


    【解决方案1】:

    当无法确定文件的总大小时,e.loadede.total 为零。您可以在 progress 函数中检查这一点:

    if (evt.lengthComputable) {
        progressCallback(e.loaded / e.total);
    }
    

    服务器还必须发送Content-Length,它在specification中定义:

    如果通过Content-Length标头知道HTTP实体主体的长度,则将lengthComputable属性初始化为true,并将total属性初始化为长度。

    另请注意,进度条不适用于file: 协议。

    我真的可以推荐非常广泛的 Mozilla 文档 - Using XMLHTTPRequest Mozilla Docs

    【讨论】:

    • 谢谢!我会看看这个!
    • 服务器是否必须交付一些东西才能使 lengthComputable 变为 true?因为我已经正确发送了 Content-Length ...
    • stackoverflow.com/questions/11127654/… 。服务器也必须发送Content-Length
    • 我已经更新了我的答案。您使用哪种服务器和编程语言?
    【解决方案2】:

    我自己也遇到了类似的问题,我在 XMLHttpRequest 上的 progress 事件的事件处理函数只执行了一次 -- 上传完成后。

    问题的原因很简单——在谷歌浏览器(可能还有其他浏览器,我没有测试)中,progress 事件只有在上传运行了一两秒时才会连续触发.换句话说,如果您的上传很快完成,那么您很可能只会获得一个 100% progress 事件。

    这是一个代码示例,其 progress 事件仅在 100% 完成时触发一次 (https://jsfiddle.net/qahs40r6/):

    $.ajax({
      xhr: function()
      {
        var xhr = new window.XMLHttpRequest();
        //Upload progress
        xhr.upload.addEventListener("progress", function(evt){
          if (evt.lengthComputable) {
            var percentComplete = evt.loaded / evt.total;
            console.log("Upload ", Math.round(percentComplete*100) + "% complete.");
          }
        }, false);
        return xhr;
      },
      type: 'POST',
      url: "/echo/json/",
      data: {json: JSON.stringify(new Array(20000))}
    });
    

    控制台输出:

    Upload  100% complete.
    

    但是如果你在数组的大小上添加一个额外的零(将有效负载大小增加 10 倍——https://jsfiddle.net/qahs40r6/1/):

    $.ajax({
      xhr: function()
      {
        var xhr = new window.XMLHttpRequest();
        //Upload progress
        xhr.upload.addEventListener("progress", function(evt){
          if (evt.lengthComputable) {
            var percentComplete = evt.loaded / evt.total;
            console.log("Upload ", Math.round(percentComplete*100) + "% complete.");
          }
        }, false);
        return xhr;
      },
      type: 'POST',
      url: "/echo/json/",
      data: {json: JSON.stringify(new Array(200000))}
    });
    

    然后你得到progress事件的正常进展:

    Upload  8% complete.
    Upload  9% complete.
    Upload  19% complete.
    Upload  39% complete.
    Upload  50% complete.
    Upload  81% complete.
    Upload  85% complete.
    Upload  89% complete.
    Upload  100% complete.
    

    此行为取决于您的 Internet 连接速度,因此您的里程会有所不同。例如,如果您使用第一个示例并使用 Chrome 开发人员工具来减慢与模拟“Slow 3G”的连接速度,那么您将看到一系列progress 事件。

    同样,如果您在本地开发并将数据上传到本地 Web 服务器,您可能永远不会看到 progress 事件,因为上传会立即完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-15
      • 1970-01-01
      相关资源
      最近更新 更多