最稳定下载方案是用a标签配合createObjectURL和download属性。需设置download属性、调用click()、及时revokeObjectURL;Blob类型应尽量匹配真实格式;大文件宜后端直传,前端需流式处理或降级提示。

直接用 window.URL.createObjectURL(blob) 创建临时 URL,再触发 a 标签下载——这是目前最稳定、兼容性最好、不依赖后端的方案。
为什么不能直接用 location.href = URL.createObjectURL(blob)
这么做在 Chrome 和 Edge 里可能触发下载,但在 Safari 和部分 iOS WebView 中会打开空白页或失败;更关键的是,location.href 无法指定文件名,浏览器默认用 “download” 或乱码命名。而 a.download 属性能明确控制保存名,且所有现代浏览器都支持该组合用法。
- 必须设置
a.download属性,否则点击后可能跳转而非下载 - 必须调用
a.click()触发,仅设置href不生效 - 下载完成后建议立即调用
window.URL.revokeObjectURL(url)释放内存,尤其在频繁生成 Blob 的场景(如导出多张图表)
Blob 构造时的类型(type)参数到底要不要填
填不填不影响下载动作本身,但会影响后续行为:不填或填错(比如把 .xlsx 写成 text/plain)可能导致双击打不开、系统识别为未知类型、甚至被安全软件拦截。实际中应尽量匹配真实内容类型:
- 文本类(.txt / .csv / .json):用
"text/plain"或更精确的"text/csv" - Excel 文件(前端生成的
.xlsx):用"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" - PDF:用
"application/pdf" - 不确定时,宁可留空(
new Blob([data])),也不要硬写错类型
大文件下载卡顿或内存爆掉怎么办
前端生成大 Blob(如 >100MB 的日志导出)时,new Blob([hugeArray]) 会一次性拷贝全部数据到内存,容易触发浏览器 OOM。此时应避免全量构造 Blob,改用流式处理:
立即学习“前端免费学习笔记(深入)”;
- 优先让后端提供直传下载链接(
Content-Disposition: attachment),这是最稳妥的大文件方案 - 若必须前端生成,考虑分块构造 +
ReadableStream+WritableStream(Chrome/Firefox 支持,Safari 仍受限) - 简单降级:对 >50MB 的数据加提示“文件较大,可能需要较长时间”,并禁用重复点击
真正容易被忽略的是 revokeObjectURL 的调用时机——很多人只在成功下载后清理,却没处理下载失败、用户取消、或脚本异常中断的情况。建议统一用 try/finally 包裹,确保 URL 总是释放。



















