标签download属性仅对同源文件有效,跨域时失效;Blob下载需显式设filename并及时revokeObjectURL;Safari对Blob URL支持有限,服务端应配Content-Disposition响应头。

用 <a> 标签加 download 属性最简单
只要目标文件同源(协议、域名、端口完全一致),<a href="xxx.pdf" download="report.pdf">下载</a> 就能触发浏览器下载,不跳转、不打开。注意:download 属性对跨域资源无效——比如链接指向 https://cdn.example.com/file.zip,点击后仍会打开或跳转,不会下载。
常见错误:把 download 写成 download="true" 或空字符串;实际只需存在该属性,或设为期望的文件名(支持中文,但部分旧版 Safari 会忽略)。
-
download值为空(download="")时,浏览器尝试从href路径提取文件名 - 如果
href是动态生成的 Blob URL,download属性必须显式指定文件名,否则下载文件可能叫unknown - Chrome 和 Firefox 支持良好;Safari 16.4+ 才支持 Blob URL +
download,更早版本需降级处理
用 JavaScript 创建 Blob 并触发下载
当文件内容来自 API 响应、用户输入或前端计算(比如导出 JSON 表格),无法直接用静态 <a>,就得靠 Blob + URL.createObjectURL()。
关键点不是“怎么创建 Blob”,而是“怎么安全释放内存”:每次调用 createObjectURL 都会生成一个引用,不手动回收会导致内存泄漏。
立即学习“前端免费学习笔记(深入)”;
使用 Puppeteer + Chrome 将 HTML 渲染为中文 PDF,自动处理图表等待、Tab 展开、动画、测高、白边消除、防分页,适用于看板、报表、网页和交互图表转 PDF。
- 下载完成后必须立即调用
URL.revokeObjectURL(url),哪怕只下载一次 - 不要在循环里反复创建 URL 却不 revoke——尤其在表格导出等高频操作中
- 注意 MIME 类型:文本类用
"text/plain"或"application/json";Excel 文件建议用"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",而非"application/octet-stream"(后者可能触发杀毒软件拦截)
const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "data.json";
a.click();
URL.revokeObjectURL(url); // 必须写在这里
服务端返回文件时,前端如何避免页面跳转
当后端接口(如 /api/export?format=csv)返回文件流,直接 window.location.href 或 <a href="/api/export"> 在某些浏览器(尤其是 Safari)会打开新页或空白页,而不是下载。
根本原因是响应头缺失或不匹配:Content-Disposition: attachment; filename="xxx.csv" 是必需的,且 Content-Type 应尽量准确(如 text/csv)。前端无法修改响应头,但可以控制请求方式。
- 用
fetch+response.blob()获取二进制数据,再走 Blob 下载流程,完全绕过跳转问题 - 避免用
XMLHttpRequest的responseType = "blob"后直接赋值给<a href>——IE11 不支持 Blob URL,需额外兼容 - 如果后端不支持
Content-Disposition,唯一可靠方案是 fetch + Blob,别试图用 iframe 或 form submit 模拟下载(不可靠、难调试)
按钮禁用与状态反馈不能省
下载过程常涉及网络请求或大文件生成,用户点击后没反应,容易重复点击——导致多次请求或生成重复文件。
最简实践:按钮点击后立即 disabled = true,下载完成或失败后再恢复;同时加个 loading 文本或 spinner。别依赖 CSS 类切换来模拟禁用,必须设置原生 disabled 属性,防止键盘回车再次触发。
- 使用
fetch时,finally块里恢复按钮状态,确保异常时也能解锁 - 如果下载耗时超过 1s,建议显示进度(仅限已知大小的文件流);对纯前端生成的 Blob,可直接算好再触发,无需中间状态
- 移动端要注意:iOS Safari 对自动
click()有限制,必须由用户手势(如onclick)触发下载逻辑,不能异步延迟后调用
download、某些企业内网浏览器会拦截 data: URL。这些边界情况没法靠一套代码兜底,得按目标环境决定是否引入 FileSaver.js 这类 polyfill,或者干脆让后端多提供一个带正确响应头的直链。


















