fetch下载文件读取进度,提示只能读取一次?

 useEffect(() => {
    const videoRef = $('.home_bg_logo_box_video_1')[0] as HTMLVideoElement;
    const videoURL = 'video/0.mp4';
    // 加载视频完成后再播放
    fetch(videoURL).then((response: any) => {
      const contentLength = response.headers.get('Content-Length');
      const fileSizeBytes = parseInt(contentLength, 10);
      let downloadedBytes = 0;
      const reader = response.body.getReader();
      function readChunk() {
        reader.read().then(({ value, done }: any) => {
          if (done) {
            console.log('done', response.body);
            // TODO 读取不到blob
            return;
          }
          downloadedBytes += value.length;
          const progress = (downloadedBytes / fileSizeBytes) * 100;
          setPre(Math.floor(progress));
          readChunk();
        });
      }

      readChunk();
    });
    // .then((blob: Blob) => {
    // init(blob());
    // });

    function init(blob: Blob) {
      videoRef.src = URL.createObjectURL(blob);

      // 当浏览器预计能够在不停下来进行缓冲的情况下持续播放指定的音频/视频时,会发生 canplaythrough 事件。
      videoRef.addEventListener('canplaythrough', () => {
        $('.home_bg_logo_box_loading').css({
          // display: 'none',
        });
        videoRef.play();
      });

      videoRef.addEventListener('ended', function () {
        // 播放结束后的操作 从第N秒开始播放
        videoRef.currentTime = 8;
        videoRef.play();
      });
    }
  }, []);

进度条可以获取到,但是我获取不到blob了。提示错误 TypeError: Failed to execute 'blob' on 'Response': body stream already read。

阅读 3.6k
1 个回答

你这个错误是因为HTTP响应体只能被读一次,用ReadableStream的pipeThrough()方法试试:

fetch(videoURL).then(response => {
  const contentLength = response.headers.get('Content-Length');
  const fileSizeBytes = parseInt(contentLength, 10);
  let downloadedBytes = 0;

  const transformer = new TransformStream({
    transform(chunk, controller) {
      downloadedBytes += chunk.length;
      const progress = (downloadedBytes / fileSizeBytes) * 100;
      setPre(Math.floor(progress));
      controller.enqueue(chunk);
    }
  });

  const blobStream = response.body.pipeThrough(transformer);
  return new Response(blobStream, { headers: response.headers }).blob();
}).then(blob => {
  init(blob);
});

MDN

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题