JavaScript实现CSV流式下载 如何展示后端接口返回大文件的下载进度
大体积CSV文件下载进度展示实现方案
核心实现逻辑
- 后端接口需要先满足两个前置条件:
- 响应头返回
Content-Length字段,标注文件的总字节大小 - 配置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
相关产品推荐
相关产品推荐

