XMLHttpRequest错误的进度

4
我在使用JavaScript上传表单并监控进度时遇到了问题。问题在于XMLHttpRequest进度事件的行为很奇怪。当真正的上传没有完成时,它会过快地达到100%,有时候甚至只是刚开始,这是通过Chrome开发工具和系统监视器进行监控的。
因此,尽管计算出的进度为100%,但我必须等待很长时间才能发送文件,同时页面似乎被卡住了。我已经阅读过杀毒软件可能是原因,但这并不是这种情况。我没有安装杀毒软件,并关闭了防火墙。我尝试使用chrome、firefox在Windows和Ubuntu以及诸如jQuery表单插件等库,但都出现了相同的行为。
有人能解释这种奇怪的行为吗?XMLHttpRequest进度事件中的loaded属性实际上计算了什么?
非常感谢您的帮助。我感觉自己像一天撞在了墙上。
以下是一个重现此问题的小代码片段:
<?php
echo "Hello!";

if(isset($_FILES['file'])){
    echo " File received";
    return;
}
?>

<form  method='post' action='' enctype='multipart/form-data'>
   <input type='file' name='file' />
   <input type='submit'>
</form>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<script>

$(document).ready(function(){
    $('form').submit(function(e){
        e.preventDefault();
        ajax = new XMLHttpRequest();
        ajax.onreadystatechange = function ()
        {
            console.log("READY STATE CHANGED");
            console.log(ajax);
        };

        ajax.upload.addEventListener("progress", function (event) {

            var percent = (event.loaded / event.total) * 100;
            console.log(percent);

        });

        ajax.open("POST", $(this).attr('action'), true);
        ajax.send(new FormData(this));
        return false;
    });

});
</script>

1
你期望得到什么结果? - guest271314
1
我期望当请求的最后一个字节发送到服务器时,进度百分比达到100%。但是,实际上我看到在上传需要超过10秒才能完成的情况下,例如在5秒钟内就已经显示为100%了。 - Bikappa
1
你不确定的是什么?字节仍然需要通过网络传输到服务器。你怎么知道这个过程需要10秒才能完成?你期望 echo " File received";event.total 等于 event.loaded 的时候被调用吗?progress 事件会分派已传输的字节,但不会监视一旦发送到网络上的字节。 - guest271314
1
是的,progress事件大约每50ms分派一次。 progress事件不是实时分派的,如果自上次调用这些子子步骤以来不到50ms,则终止这些子子步骤。如果上传侦听器标志已设置,则在XMLHttpRequestUpload对象上触发一个名为progress的进度事件,其中包含请求体传输的字节数和请求体总字节数。https://xhr.spec.whatwg.org/#xmlhttprequestupload。 - guest271314
1
我知道这个问题很老了,但我可能能够为这个问题添加一些信息。这似乎只发生在Windows上。我们在其中一个页面上遇到了同样的问题。上传一个60MB的文件,速度约为0.4mb/s,在Windows上在两秒内跳至100%...让我们等待另外几分钟的响应 - 在所有主要浏览器上都会发生。在Linux上(Chrome和Firefox)相同的操作以约0.4 mb/s的速度显示进度...这应该是期望的行为。 - Tobi
显示剩余18条评论
1个回答

2
XMLHttpRequestUpload的progress事件大约每50毫秒分派一次。XMLHttpRequestUpload按照传输的body字节分派事件。据我所知,XMLHttpRequestUpload不会监视与body传输字节相关的网络性能,并且不等待服务器响应。
请参见生成上传进度通知 当说要生成进度通知时,在下载进行时,排队一个任务来触发名为progress的进度事件,大约每50毫秒或每接收到一个字节触发一次,以较少的频率触发。
当说要生成上传进度通知时,请执行以下步骤:
  • 在请求实体正被上传且上传完成标志为 false 时,排队一个任务,在每传输完每个字节或大约 50 毫秒之后,以最少的频率向 XMLHttpRequestUpload 对象触发名为 progress 的进度事件。

  • 如果请求实体主体已成功上传且上传完成标志仍为false,则排队运行以下子步骤:

    1. 将上传完成标志设置为true。

    2. 触发名为load的进度事件到XMLHttpRequestUpload对象。

    3. 触发名为loadend的进度事件到XMLHttpRequestUpload对象。


另请参阅:如何在服务器实时写入上传文件大小而不会在服务器和客户端两端阻塞时读取并输出?

这并没有解决实际的问题。请参考Tobi对这个问题的评论。看起来这是Windows的一个bug。 - Tim S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接