download属性仅对同源静态资源生效,跨域链接、后端接口或Blob URL需分别通过服务端Content-Disposition响应头、JS Blob构造或iOS长按下载等方式实现下载。

download 属性为什么有时不生效
直接给 <a> 标签加 download 属性,只在**同源 URL** 下才真正触发下载;跨域链接(比如指向 CDN 或 API 接口的 href="https://example.com/file.pdf")会被浏览器静默忽略该属性,点击后仍会跳转或在线打开。
常见错误现象:download 属性存在但右键“另存为”才弹出保存框,点击链接却直接导航或预览——这说明浏览器没走下载流程。
- 必须确保
href指向的是**同源静态资源路径**(如/assets/report.xlsx),不能是后端接口地址(如/api/export?format=csv) - 如果资源由后端动态生成,需服务端配合设置
Content-Disposition: attachment; filename="xxx"响应头,此时download属性可省略 - Firefox 当前完全不支持
download属性对 Blob URL 的触发(Chrome/Edge 支持)
用 JavaScript 创建 Blob URL 并触发下载
当你要下载的内容来自 JS 生成的数据(如导出 JSON 表格、前端渲染的 PDF),就得绕过 download 的同源限制,手动构造 Blob + URL。
核心思路:把数据转成 Blob,用 URL.createObjectURL() 得到本地可访问的 URL,再创建临时 <a> 标签并调用 .click()。
立即学习“前端免费学习笔记(深入)”;
const data = JSON.stringify({name: "test", value: 42});
const blob = new Blob([data], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "config.json";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url); // 及时释放引用-
a.download在 Blob URL 场景下只是建议文件名,浏览器可能忽略(尤其 Safari),实际保存名以Content-Disposition或 URL 路径为准 - 必须调用
a.click(),不能仅靠用户点击——因为临时<a>是 JS 创建的,不在 DOM 初始结构中 - 记得
URL.revokeObjectURL(url),否则内存泄漏风险随下载次数上升
后端接口返回文件流时的正确用法
如果你的 href 指向的是一个后端接口(如 /export/csv),就别依赖 download 属性了——它大概率失效。关键在服务端响应头。
服务端必须返回以下两个关键响应头:
Content-Disposition: attachment; filename="report.csv"-
Content-Type: text/csv(或对应真实类型,如application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)
此时,哪怕去掉 download 属性,只要 <a href="/export/csv">导出 CSV</a>,点击就会触发下载。加上 download 也没坏处,但不起决定作用。
注意:Nginx / CDN 可能缓存或覆盖响应头,务必检查真实响应中是否包含 Content-Disposition —— 用浏览器 DevTools 的 Network 面板看 Headers 选项卡。
移动端 Safari 的特殊处理
iOS Safari 对 <a download> 和 Blob URL 下载都限制极严:无法通过 JS 触发 .click() 下载,也不支持 download 属性(即使同源)。
目前唯一可靠方案是后端提供带 Content-Disposition 的直链,并引导用户长按链接选择“下载”。前端无法绕过。
- 不要在 iOS 上尝试用
location.href = blobUrl或window.open(blobUrl)代替<a>.click(),它们都不触发下载 - 如果必须前端生成文件,可考虑将内容 base64 编码后拼成 data URL:
href="data:text/csv;base64,...",但仅适用于小文件(iOS 对 data URL 长度敏感) - 大文件或稳定体验要求高时,放弃前端下载,改用后端直出 + 用户手动操作
真正麻烦的从来不是怎么写那行 download,而是搞清当前资源来源、浏览器能力边界和服务端是否配好了头——三者缺一,都会卡在“点一下没反应”。



















