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

JS分块下载大文件如何实现带百分比的下载进度显示

分块下载实时进度改造方案

原有实现无进度的核心原因是逻辑上等待所有分片完整返回、拼接成最终Blob后才触发浏览器保存动作,下载过程完全在JS逻辑里静默执行,浏览器无法感知中间状态。要实现和原生下载一致的实时百分比进度,按以下逻辑改造即可:

  • 提前统计所有分片的总字节大小:通过响应头的Content-Length字段拿到每个分片的大小,累加得到完整文件总大小,作为进度计算的基数。
  • 流式读取分片响应:不要直接用res.blob()等待整个分片下载完成,而是通过ReadableStream逐块读取响应数据,每读取到一段数据就累加已下载字节数,实时计算进度百分比。
  • 进度同步更新到UI:计算得到的百分比可以直接绑定到自定义的进度条、进度文本组件上,实现实时反馈。
  • 所有分片读取完成后,拼接成完整Blob触发文件保存,最后记得释放生成的对象URL避免内存泄漏。

改造后完整代码

async function testDownload()
{
  try{
    const urls = ['https://localhost:54373/analyzer/test1','https://localhost:54373/analyzer/test2']
    const chunkList = []
    let totalFileSize = 0
    let loadedSize = 0

    // 预取所有分片的总大小
    for (const url of urls) {
      const headResp = await fetch(url, { method: 'HEAD' })
      if (!headResp.ok) throw new Error('分片信息获取失败')
      totalFileSize += Number(headResp.headers.get('Content-Length')) || 0
    }

    // 逐块流式下载,实时更新进度
    for (const url of urls) {
      const resp = await fetch(url)
      if (!resp.ok || resp.status !== 200) {
        throw new Error('下载失败');
      }

      const reader = resp.body.getReader()
      const chunkParts = []
      while (true) {
        const { done, value } = await reader.read()
        if (done) break
        chunkParts.push(value)
        loadedSize += value.length
        // 计算当前进度,此处替换为你自己的UI更新逻辑
        const progress = Math.round((loadedSize / totalFileSize) * 100)
        console.log(`下载进度:${progress}%`)
        // 示例:更新页面进度条 document.querySelector('#download-progress').style.width = `${progress}%`
      }
      chunkList.push(new Blob(chunkParts))
    }

    // 全部下载完成后触发保存
    const fullFile = new Blob(chunkList)
    const fileUrl = window.URL.createObjectURL(fullFile)
    const a = document.createElement('a')
    a.href = fileUrl
    a.download = "WTF.ini"
    a.click()
    // 释放临时URL
    window.URL.revokeObjectURL(fileUrl)
  } 
  catch(e){
    console.error(e)
  }
}

补充说明:如果你的分片接口不支持HEAD请求,可以去掉单独的HEAD请求步骤,在第一次GET请求拿响应的时候先读取Content-Length累加总大小,再开始读流,能减少一次网络请求。如果分片大小是固定的,也可以直接用分片数*单分片大小计算总大小,不用额外发请求。

内容的提问来源于stack exchange,提问作者Alex Soryn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 13:42:21