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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3352555/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 00:55:34  来源:igfitidea点击:

XHR Upload Progress is 100% from the start

javascriptajaxxmlhttprequest

提问by Ben Robinson

I'm trying out the new XMLHTTPRequestUpload feature to upload some files to a php script, it mostly works fine, the upload starts, I get the finish response etc - but the progress doesn't seem to work.

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

Looking that the event.loaded value - In firefox I seem to get a random value between 0 and the file size; in Chrome (where I'm mostly working) I get the total file size, even though the readystate hasn't reached '4' and the Developer Tools window still shows the file to be loading?

查看 event.loaded 值 - 在 firefox 中,我似乎得到了一个介于 0 和文件大小之间的随机值;在 Chrome(我主要工作的地方)中,我得到了总文件大小,即使就绪状态尚未达到“4”并且“开发人员工具”窗口仍显示要加载的文件?

Any ideas?

有任何想法吗?

Heres my code:

这是我的代码:

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);

Many thanks

非常感谢

Ben

采纳答案by R Hill

I also recently had some difficulty setting an event listener for XHR onprogress events. I ended up implementing it as an anonymous function, which works beautifully:

我最近也遇到了一些困难,为 XHR onprogress 事件设置事件侦听器。我最终将它实现为一个匿名函数,它工作得很好:

xhr.upload.onprogress = function(evt)
{
    if (evt.lengthComputable)
    {
        var percentComplete = parseInt((evt.loaded / evt.total) * 100);
        console.log("Upload: " + percentComplete + "% complete")
    }
};

I stumbled across a lotof other gotchas along the way, though, so it's quite likely one of those was tripping up my event listener. The only other difference between what you've got there and my setup is that I'm using xhr.sendAsBinary().

不过,我在此过程中偶然发现了许多其他问题,因此很可能其中之一是绊倒了我的事件侦听器。你在那里得到的和我的设置之间唯一的另一个区别是我使用的是 xhr.sendAsBinary()。

回答by Elliot B.

I ran into a similar issue myself, where my event handler function for progressevents on XMLHttpRequestwas executed only once -- when the upload was complete.

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

The cause of the problem ended up being simple -- in Google Chrome (possibly other browsers too, I did not test), the progressevent will only fire in succession if the upload had been running for a second or two. In other words, if your upload finishes quickly, then you'll likely just get one 100% progressevent.

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

Here's an example of code whose progressevent only fires once at 100% complete ( https://jsfiddle.net/qahs40r6/):

这是一个代码示例,其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))}
});

Console output:

控制台输出:

Upload  100% complete.

But if you add an extra zero to the size of the array (increasing the payload size by a factor of 10 -- https://jsfiddle.net/qahs40r6/1/):

但是,如果您为数组的大小添加一个额外的零(将有效负载大小增加 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))}
});

Then you get the normal progression of progressevents:

然后你会得到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.

This behavior depends upon how fast your Internet connection is, so your mileage will vary. For example, if you take the first example and use Chrome Developer Tools to slow your connection to a simulated "Slow 3G", then you will see the series of progressevents.

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

Similarly, if you are developing locally and uploading data to a local web server, you'll likely never see progressevents because the upload will finish instantly. This is likely what @brettjonesdev was seeing in localhost vs remote prod deployments.

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

回答by JohnGin

I have similar issue and I found reason. In my case the troublemaker is antivirus (bitdefender)on my PC. When I turn off bitdefender protection, the progress behaves exactly as it should.

我有类似的问题,我找到了原因。就我而言,麻烦制造者是我 PC 上的防病毒软件(bitdefender)。当我关闭 bitdefender 保护时,进度完全按照它应该的方式运行。