如何从 XMLHttpRequest 获得进度

2022-08-30 04:17:40

是否有可能获取 XMLHttpRequest 的进度(上传的字节数,下载的字节数)?

这对于在用户上载大文件时显示进度条非常有用。标准API似乎不支持它,但也许在任何浏览器中都有一些非标准扩展?毕竟,这似乎是一个非常明显的功能,因为客户端知道上传/下载了多少字节。

注意:我知道“轮询服务器以获取进度”替代方案(这就是我现在正在做的事情)。这样做的主要问题(除了复杂的服务器端代码)是,通常,在上传大文件时,用户的连接是完全软管化的,因为大多数ISP的上游性能较差。因此,提出额外的请求并不像我希望的那样响应。我希望有一种方法(也许是非标准的)来获取这些信息,浏览器始终拥有这些信息。


答案 1

对于上传的字节,这很容易。只需监视事件即可。浏览器知道它必须上传的文件的大小和上传数据的大小,因此它可以提供进度信息。xhr.upload.onprogress

对于下载的字节(获取信息时),这有点困难,因为浏览器不知道在服务器请求中将发送多少字节。在这种情况下,浏览器唯一知道的是它接收的字节的大小。xhr.responseText

有一个解决方案,在服务器脚本上设置一个标头就足够了,以便获得浏览器将要接收的字节的总大小。Content-Length

欲了解更多信息,请访问 https://developer.mozilla.org/en/Using_XMLHttpRequest

示例:我的服务器脚本读取 zip 文件(需要 5 秒钟):

$filesize=filesize('test.zip');

header("Content-Length: " . $filesize); // set header length
// if the headers is not set then the evt.loaded will be 0
readfile('test.zip');
exit 0;

现在我可以监视服务器脚本的下载过程,因为我知道它的总长度:

function updateProgress(evt) 
{
   if (evt.lengthComputable) 
   {  // evt.loaded the bytes the browser received
      // evt.total the total bytes set by the header
      // jQuery UI progress bar to show the progress on screen
     var percentComplete = (evt.loaded / evt.total) * 100;  
     $('#progressbar').progressbar( "option", "value", percentComplete );
   } 
}   
function sendreq(evt) 
{  
    var req = new XMLHttpRequest(); 
    $('#progressbar').progressbar();    
    req.onprogress = updateProgress;
    req.open('GET', 'test.php', true);  
    req.onreadystatechange = function (aEvt) {  
        if (req.readyState == 4) 
        {  
             //run any callback here
        }  
    };  
    req.send(); 
}

答案 2

火狐支持 XHR 下载进度事件

编辑 2021-07-08 10:30 PDT

上面的链接是死的。在Mozilla WebDev网站上进行搜索时,发现了以下链接:

https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent

它描述了如何将 progress 事件与 XMLHttpRequest 一起使用,并提供了一个示例。我在下面包含了示例:

var progressBar = document.getElementById("p"),
    client = new XMLHttpRequest()
client.open("GET", "magical-unicorns")
client.onprogress = function(pe) {
  if(pe.lengthComputable) {
    progressBar.max = pe.total
    progressBar.value = pe.loaded
  }
}
client.onloadend = function(pe) {
  progressBar.value = pe.loaded
}
client.send()

我也发现了这个链接,我认为原始链接指向了这个链接。

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/progress_event