You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Performance API无法实时反馈图片下载transferSize,如何实现实时监控?

问题描述

我正在使用Performance API监控图片的下载进度,用于实时JPG图像流场景并检测下载是否停滞,希望监控已下载大小是否持续增长。但resource事件仅在下载完成时触发,我的使用代码如下:

var currentObserver = null;
function setupObserver(observeUrl) {
    currentObserver = null;
    currentObserver = new PerformanceObserver((list, obj) => {
      list.getEntries().forEach((entry) => {
        if(entry.name.indexOf(observeUrl) > 0) {
            console.log("entry transferSize:", observeUrl, entry.transferSize);
        }
      });
    });
    currentObserver.observe({ entryTypes: ["resource"] });
}

请问是否有办法在图片下载过程中获取更多更新,或者是否需要监听其他entryType?感谢您提供任何思路!

解决方案
  • Performance API 的 resource 类型条目确实仅在资源完全下载完成后才会生成,无法用于获取下载过程中的实时进度更新;其他内置的 entryType(比如navigation、mark等)也没有提供实时下载进度的能力。

  • 要监控图片下载的实时进度并检测停滞,更可靠的方案是直接使用XMLHttpRequest (XHR) 或 Fetch API 的流式处理能力:

    1. 使用XMLHttpRequest监听进度
      XHR提供了onprogress事件,可以实时获取已加载字节数和总字节数,同时可以通过定时器检测进度是否停滞:

      function monitorImageDownload(url) {
          let lastLoaded = 0;
          let stagnationTimer = null;
          const xhr = new XMLHttpRequest();
          
          xhr.open('GET', url, true);
          xhr.responseType = 'blob'; // 若需后续展示图片,可设为blob
          
          // 实时进度回调
          xhr.onprogress = function(e) {
              if (e.lengthComputable) {
                  const loaded = e.loaded;
                  const total = e.total;
                  console.log(`已下载: ${loaded}/${total} (${(loaded/total*100).toFixed(2)}%)`);
                  
                  // 检测是否停滞
                  if (loaded === lastLoaded) {
                      if (!stagnationTimer) {
                          // 超过3秒没变化判定为停滞
                          stagnationTimer = setTimeout(() => {
                              console.error('下载已停滞');
                          }, 3000);
                      }
                  } else {
                      lastLoaded = loaded;
                      if (stagnationTimer) {
                          clearTimeout(stagnationTimer);
                          stagnationTimer = null;
                      }
                  }
              }
          };
          
          xhr.onload = function() {
              if (stagnationTimer) clearTimeout(stagnationTimer);
              console.log('下载完成');
              // 若需展示图片,将blob转为objectURL赋值给img
              // const img = document.createElement('img');
              // img.src = URL.createObjectURL(xhr.response);
              // document.body.appendChild(img);
          };
          
          xhr.onerror = function() {
              console.error('下载失败');
          };
          
          xhr.send();
          return xhr;
      }
      
    2. 使用Fetch API结合ReadableStream(适合流式场景)
      对于实时JPG流场景,Fetch的ReadableStream可以逐段读取下载的数据,同时统计已加载字节数:

      async function monitorStreamDownload(url) {
          let totalLoaded = 0;
          let lastLoaded = 0;
          let stagnationTimer = null;
          
          const response = await fetch(url);
          if (!response.ok) throw new Error(`请求失败: ${response.status}`);
          
          const reader = response.body.getReader();
          
          while (true) {
              const { done, value } = await reader.read();
              if (done) break;
              
              totalLoaded += value.length;
              console.log(`已下载字节数: ${totalLoaded}`);
              
              // 检测停滞
              if (totalLoaded === lastLoaded) {
                  if (!stagnationTimer) {
                      stagnationTimer = setTimeout(() => {
                          console.error('流式下载已停滞');
                      }, 3000);
                  }
              } else {
                  lastLoaded = totalLoaded;
                  if (stagnationTimer) {
                      clearTimeout(stagnationTimer);
                      stagnationTimer = null;
                  }
              }
              
              // 可在此对流数据做处理,比如实时解析JPG片段(如果是分段流)
              // processChunk(value);
          }
          
          if (stagnationTimer) clearTimeout(stagnationTimer);
          console.log('流式下载完成');
      }
      
  • 如果原本是用<img>标签直接加载图片,需要改为先通过XHR/Fetch下载,再将获取到的Blob转为objectURL赋值给<img>的src属性,这样既能监控进度,又不影响图片展示。

内容的提问来源于stack exchange,提问作者Tom Deblauwe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 14:41:18