跨域时a标签download属性被浏览器静默忽略,因同源策略禁止控制跨域资源下载;可靠方案是fetch获取Blob后创建同源URL下载,需注意Safari兼容性、内存泄漏及错误处理。

无效。浏览器会静默忽略 download 属性,点击后通常直接跳转或在新标签页打开文件,而不是下载,更不会按你指定的文件名保存。
为什么跨域时 download 会被忽略
这是同源策略的硬性限制:只要 a 标签的 href 与当前页面协议、域名、端口任一不同,就被视为跨域。包括以下常见情况:
-
http://a.com页面中链接指向https://a.com/file.pdf(协议不同) -
https://www.site.com页面中链接指向https://cdn.site.com/img.jpg(子域名不同) -
https://localhost:3000页面中链接指向https://127.0.0.1:3000/data.xlsx(主机名不同)
浏览器不让你控制跨域资源的下载行为,本质是防止恶意站点伪造下载链接、篡改文件名诱导用户执行危险文件。这不是 bug,是安全设计。
fetch + Blob 是目前最可靠方案
绕过限制的核心思路是:不直接链接跨域 URL,而是先用 fetch(或 XMLHttpRequest、axios)把文件内容拉到前端内存,再用 Blob 和 URL.createObjectURL() 构造一个同源临时地址。
关键实操点:
- 必须设置
responseType: 'blob'(axios)或使用response.blob()(fetch),否则拿到的是文本或乱码 - 创建的
a元素需动态插入document.body后再调用.click(),否则 Safari 等浏览器可能拒绝触发下载 - 下载完成后务必调用
URL.revokeObjectURL(url),否则 Blob 对象长期驻留内存,造成泄漏 - 大文件(如 >50MB)慎用此法——全量加载进内存可能卡死页面,应考虑服务端直链 +
Content-Disposition配合
Safari 全系不支持 download 属性
即使同源,Safari 也完全无视 download。所以如果你的用户包含 iOS/macOS 用户,fetch + Blob 不是“备选方案”,而是必选项。别依赖 if ('download' in HTMLAnchorElement.prototype) 做兼容判断——它在 Safari 返回 true,但实际无效。
真正容易被忽略的是错误处理:fetch 失败时没有降级提示,用户点按钮毫无反应;Blob 构造失败(比如响应不是二进制)也不会抛错,只是下出一个空文件。加一层 response.ok 判断和 response.headers.get('content-type') 校验,比写十个 console.log 更有用。

















