XHR上传进度从一开始就是100%

时间:2010-07-28 11:56:07

标签: javascript ajax xmlhttprequest

我正在尝试新的XMLHTTPRequestUpload功能将一些文件上传到php脚本,它大部分工作正常,上传开始,我得到完成响应等 - 但进展似乎不起作用。

查看event.loaded值 - 在firefox中,我似乎得到一个介于0和文件大小之间的随机值;在Chrome(我主要工作的地方)我得到了总文件大小,即使readystate没有达到'4'并且Developer Tools窗口仍然显示要加载的文件?

有什么想法吗?

继承我的代码:

var xhr = new XMLHttpRequest()

xhr.upload.addEventListener('progress', function(event) {
    if (event.lengthComputable) {
        $('ajaxFeedbackDiv').innerHTML = event.loaded + ' / ' + event.total;
    }
}, false);

xhr.onreadystatechange = function(event) {
    if (event.target.readyState == 4) {
        updateFileList();
    }
};

xhr.open("POST", "_code/upload.php");
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("X-File-Size", file.size);
xhr.setRequestHeader("X-File-Type", file.type);
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr(file);

非常感谢

3 个答案:

答案 0 :(得分:17)

我最近在设置XHR onprogress事件的事件监听器时遇到了一些困难。我最终将它作为一个匿名函数实现,它运行得很漂亮:

xhr.upload.onprogress = function(evt)
{
    if (evt.lengthComputable)
    {
        var percentComplete = parseInt((evt.loaded / evt.total) * 100);
        console.log("Upload: " + percentComplete + "% complete")
    }
};
然而,我偶然发现了其他陷阱的很多,所以很可能其中一个是绊倒了我的事件监听器。你在那里和我的设置之间唯一的区别是我正在使用xhr.sendAsBinary()。

答案 1 :(得分:4)

我自己遇到了类似的问题,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.

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

同样,如果您在本地开发并将数据上传到本地Web服务器,您可能永远不会看到progress事件,因为上传将立即完成。这可能是@brettjonesdev在localhost和远程prod部署中看到的。

答案 2 :(得分:1)

我有类似的问题,并且找到了原因。在我的情况下,麻烦制造者是我的PC上的防病毒软件(bitdefender)。当我关闭bitdefender保护时,进度的行为将完全正常。