5

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

根据 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)

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

4

2 回答 2

2

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

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

服务器还必须发送规范Content-Length中定义的内容:

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

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

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

于 2013-03-19T08:54:05.963 回答
1

我自己也遇到了类似的问题,我的事件处理函数progressXMLHttpRequest执行了一次——上传完成时。

问题的原因很简单——在谷歌浏览器中(可能还有其他浏览器,我没有测试),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事件,因为上传会立即完成。

于 2017-11-10T18:43:12.163 回答