download属性跨域时必然失效,是浏览器安全策略而非bug;仅同源URL或blob:/data:协议生效,跨域需fetch+Blob绕过或后端代理,iOS Safari不支持脚本触发下载。

download 属性在跨域时必然失效,这不是 bug,是浏览器强制执行的安全策略——别试了,加了也没用。
为什么跨域时 download 属性被忽略
Chrome、Firefox、Edge 都只对同源 URL(协议、域名、端口完全一致)或 blob:/data: 协议生效。指向 https://cdn.example.com/report.pdf 或 https://api.example.com/export 的 <a> 标签,即使写了 download="report.pdf",浏览器也会静默丢弃该属性,退化为跳转或新标签页打开 PDF。
控制台不报错,Network 面板能看到请求发出,但点击后没下载——这是最典型的失效表现。
- 同源示例:
/assets/data.xlsx、http://localhost:3000/files/log.zip✅ - 跨域示例:
https://oss.aliyuncs.com/file.csv、https://api.example.com/v1/export?format=pdf❌ - 特别注意:
http://和https://视为不同源;localhost:3000和127.0.0.1:3000也跨域
fetch + Blob 是目前最通用的前端绕过方案
核心逻辑:用 fetch 拉取跨域资源(需服务端开启 CORS),转成 Blob,再用 URL.createObjectURL() 生成本地可信任 URL,最后绑定 download 属性触发下载。
立即学习“前端免费学习笔记(深入)”;
关键点:
- 服务端必须返回
Access-Control-Allow-Origin: *(或指定域名),否则fetch直接失败 - 响应类型要设为
arrayBuffer或直接调用response.blob(),不能依赖response.text()处理二进制 - 文件名必须显式传入
a.download,不能依赖后缀自动补全——Firefox 尤其要求download="report.pdf"而非download="report" - 记得调用
URL.revokeObjectURL(url)释放内存,尤其在频繁下载场景下
简短示例:
async function downloadFromUrl(url, filename) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const blob = await response.blob();
const urlObj = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = urlObj;
a.download = filename; // 必须带后缀
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(urlObj);
} catch (err) {
console.error('下载失败:', err);
}
}
大文件或生产环境建议走后端代理
前端 fetch + Blob 方案在 >100MB 文件上容易卡顿、OOM 或触发 Safari 的 URL 失效(iOS Safari 15.4+ 才稳定支持 createObjectURL),且无法做下载审计、限流、权限校验。
更可靠的路径是:前端请求一个同源接口(如 /api/download?file_id=abc123),后端拉取远端资源,设置标准响应头:
Content-Disposition: attachment; filename="invoice-2024.pdf"Content-Type: application/pdf- (可选)
Content-Length和Cache-Control: no-cache
这样前端仍可用原生 <a href="/api/download?..." download="invoice.pdf">,既轻量又可控。
真正容易被忽略的是:iOS Safari 全系不支持脚本触发下载(.click() 无效),哪怕你用了 fetch + Blob,在 iPhone 上也大概率白忙一场——这时候只能靠后端生成直链 + 同源跳转,或者引导用户长按链接手动“保存到文件”。



















