给链接加上 download 属性,点击后文件却在浏览器里直接打开了 📂。download 失效不是玄学,按下面清单逐项排查,九成情况能在前两步定位。

排查清单
一、资源是否跨域 🔍
download 只对本源地址生效。链接指向第三方域名或 CDN 独立域名时,浏览器出于安全策略直接忽略该属性。这是失效的第一道关,也是最常见的一道。
二、响应头是否指定了处理方式
服务端返回 Content-Disposition: inline 时,浏览器优先按响应头内联展示。跨域场景下响应头更是唯一决定因素,download 属性没有发言权。
三、文件类型是否本身可预览
PDF、图片、纯文本属于浏览器原生可渲染类型。同源时 download 仍能强制下载,跨域时这类文件一律按预览处理,表现为点击后打开新页面。
四、链接是否为动态生成
JS 创建的 a 元素需要显式设置 a.download = '文件名' 再触发 click。只设 href 不设 download,行为退化为普通跳转。
两条可靠的替代路径
服务端方案:让响应携带 Content-Disposition: attachment; filename="report.pdf"。与域名无关,优先级最高,最为稳妥 📁。
前端方案:先 fetch 拿到内容转成 Blob,再生成对象 URL 触发下载:
const res = await fetch(url);
const blob = await res.blob();
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'report.pdf';
a.click();
Blob 地址属于页面同源,download 恢复生效。前提是目标接口允许跨域读取,否则 fetch 阶段就被拦下 ⚠️。
结论:同源检查先行,响应头其次,都不行就走 attachment 响应头或 Blob 对象 URL,两条路径必有一条通 ✅。
