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

JavaScript实现CSV流式下载 如何展示后端接口返回大文件的下载进度

大体积CSV文件下载进度展示实现方案

核心实现逻辑

  • 后端接口需要先满足两个前置条件:
    1. 响应头返回Content-Length字段,标注文件的总字节大小
    2. 配置CORS跨域规则,添加Access-Control-Expose-Headers: Content-Length,允许前端读取该响应头
  • 前端通过支持流式读取的请求API(XMLHttpRequest / Fetch API)接收响应数据,实时统计已接收的字节数,结合总大小计算下载进度百分比

代码示例

1. XMLHttpRequest 实现(兼容性最好,支持所有主流浏览器、IE10+)

function downloadCsvWithProgress(url, fileName) {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'blob';

  // 监听进度事件
  xhr.onprogress = function(event) {
    if (event.lengthComputable) {
      // 计算进度百分比,保留1位小数
      const percent = ((event.loaded / event.total) * 100).toFixed(1);
      // 这里替换成你自己的进度更新逻辑,比如赋值给UI组件
      console.log(`下载进度:${percent}%`);
    } else {
      // 拿不到总大小,只能展示已下载字节数
      console.log(`已下载:${(event.loaded / 1024 / 1024).toFixed(2)}MB`);
    }
  };

  xhr.onload = function() {
    if (xhr.status === 200) {
      // 生成下载链接触发下载
      const blob = xhr.response;
      const downloadUrl = window.URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = downloadUrl;
      a.download = fileName;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      // 释放内存
      window.URL.revokeObjectURL(downloadUrl);
      console.log('下载完成');
    } else {
      console.error('下载失败,状态码:', xhr.status);
    }
  };

  xhr.onerror = function() {
    console.error('请求异常,请检查网络或接口');
  };

  xhr.send();
}

// 调用示例
// downloadCsvWithProgress('你的后端CSV接口地址', '导出数据.csv')

2. Fetch API 实现(适合现代前端项目,Chrome 42+、Firefox 39+支持)

async function downloadCsvWithProgress(url, fileName) {
  const response = await fetch(url);
  if (!response.ok) throw new Error(`接口请求失败:${response.status}`);
  
  // 读取文件总大小
  const totalSize = Number(response.headers.get('content-length'));
  let loadedSize = 0;
  const reader = response.body.getReader();
  const chunks = [];

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    chunks.push(value);
    loadedSize += value.length;
    // 计算进度
    if (totalSize) {
      const percent = ((loadedSize / totalSize) * 100).toFixed(1);
      console.log(`下载进度:${percent}%`);
    } else {
      console.log(`已下载:${(loadedSize / 1024 / 1024).toFixed(2)}MB`);
    }
  }

  // 合并数据生成Blob触发下载
  const blob = new Blob(chunks, { type: 'text/csv' });
  const downloadUrl = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = downloadUrl;
  a.download = fileName;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  window.URL.revokeObjectURL(downloadUrl);
}

注意事项

  • 若后端采用流式输出CSV且无法提前确定文件总大小,无法计算精确的百分比进度,可改为展示实时已下载大小的提示
  • 超过500MB的超大文件建议额外加断点续传逻辑,避免网络波动导致下载失败后需要重新下载全量文件
  • 下载完成后必须调用URL.revokeObjectURL()释放Blob占用的内存,避免页面长时间运行出现内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 16:27:02