download属性仅对同源url、blob url和data url生效,跨域链接下必然失效;服务端需配合设置content-disposition响应头;ios safari完全不支持该属性,大文件下载需后端兜底。

download 属性在跨域链接下直接失效
浏览器明确禁止对跨域 URL 使用 download 属性——哪怕你写了 <a href="https://example.com/file.pdf" download></a>,点击后也只会跳转或打开,绝不会触发下载。这是安全策略,不是 bug,也没法绕过。
常见错误现象:download 属性存在但没反应,控制台无报错,Network 面板里请求状态是 200,但页面跳转了或新标签页打开了文件。
- 只对同源 URL(即
href和当前页面协议、域名、端口完全一致)生效 - 对 Blob URL 或 data URL 有效,因为它们属于“同源生成”
- 对相对路径(如
/assets/report.xlsx)也有效,只要服务端返回的响应头允许(见下一条)
服务端未设置 Content-Disposition 导致浏览器不触发下载
即使 download 属性生效,如果服务端返回的响应头里没有 Content-Disposition: attachment; filename="xxx",部分浏览器(尤其是 Safari 和旧版 Edge)仍可能选择内嵌预览而非下载。
这不是前端能单方面解决的问题,必须后端配合:
- 静态资源:Nginx 可加
add_header Content-Disposition "attachment; filename=$1";(配合 location 正则捕获文件名) - Node.js/Express:用
res.setHeader("Content-Disposition", 'attachment; filename="data.csv"'); - 注意:
filename值不能含路径、特殊字符,建议 URL encode(如中文名)
用 JavaScript + Blob 模拟 download 属性的通用方案
当无法控制服务端或必须处理跨域资源时,唯一可靠方式是先 fetch 内容,再构造 Blob URL 触发下载。但这要求目标资源支持 CORS(否则 fetch 失败)。
示例逻辑:
fetch('https://api.example.com/export.csv')
.then(res => {
if (!res.ok) throw new Error('Fetch failed');
return res.blob();
})
.then(blob => {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'export.csv'; // 这里可动态命名
a.click();
URL.revokeObjectURL(url); // 用完立即释放
});
- 必须确保响应类型是可读的(如
text/csv、application/pdf),二进制资源(如图片)也适用 - 大文件(>100MB)慎用,Blob 构造和内存占用可能卡顿或崩溃
-
URL.revokeObjectURL必须调用,否则内存泄漏
移动端 Safari 对 download 属性几乎完全忽略
iOS Safari 不支持 download 属性,无论同源与否,点链接一律打开预览。这是硬性限制,连 Blob 方案在某些 iOS 版本上也会失败(尤其 PDF 或 Excel)。
实际能做的只有:
- 检测
navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome') - 对 iOS 用户降级提示:“请长按链接 → ‘下载链接’”,并确保链接指向可直接下载的同源地址
- 避免依赖自动下载,关键业务改用后端生成带签名的临时直链(如
/download/token=abc123),由服务端设置正确 headers
真正麻烦的是既要兼容老 Safari,又要处理跨域,还得支持大文件——这时候就得接受:前端没银弹,得靠后端兜底。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











