download属性仅对同源url生效;跨域时被浏览器静默忽略,需用fetch+blob构造同源url或由服务端设置content-disposition响应头强制下载。

download属性只对同源URL生效
浏览器出于安全限制,download 属性仅在链接指向**同源资源**(即协议、域名、端口完全一致)时才会触发强制下载;若 a 标签的 href 是跨域地址(比如 https://cdn.example.com/file.pdf),点击后仍会跳转或在新标签页打开,不会下载。
常见错误现象:@#@#@#@#@#@#@#@#@#@0 点击后没反应或直接打开文件——大概率是跨域导致的静默失效。
- 检查控制台是否出现类似
download attribute has no effect on cross-origin links的警告 - 本地开发时用
file://协议也无效,必须走http://或https://服务 - 同源但路径含查询参数(如
/api/export?id=123)一般可用,但需后端返回正确的Content-Disposition: attachment头才更可靠
如何让跨域文件也能“强制保存”
当资源必然跨域(如对象存储 OSS、CDN 文件),不能依赖 download 属性,得换路子:用 fetch + Blob + URL.createObjectURL 构造本地可下载链接。
关键点在于绕过浏览器对跨域 a[download] 的拦截,把响应体转为 Blob 后再创建同源 URL:
fetch('https://cdn.example.com/data.zip')
.then(res => res.blob())
.then(blob => {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'data.zip';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url); // 及时释放内存
});
- 注意
fetch请求需服务端允许 CORS(返回Access-Control-Allow-Origin: *或指定域名) - 大文件慎用此法,Blob 会暂存于内存,可能触发 OOM;超过 50MB 建议改用服务端直链 + 同源代理
- IE 不支持
fetch和Blob,需降级为XMLHttpRequest+responseType: 'blob'
download属性的文件名行为细节
download 属性值不是“建议名”,而是**强制使用的文件名**(不含路径、不继承原始 URL 中的文件名)。但它有隐式规则:
- 若值为空字符串(
download=""),浏览器会尝试从hrefURL 解析文件名,失败则 fallback 到unknown - 若值含非法字符(如
/、\、控制字符),浏览器会忽略该属性,退化为普通跳转 - Chrome 和 Edge 对中文名支持良好;Safari 在某些版本中会把中文名转成
download.bin,需后端配合设置Content-Disposition头 - 不要写成
download="/path/to/name.pdf"—— 路径部分会被丢弃,只取末尾name.pdf
服务端配合才是稳定方案
纯前端靠 download 或 Blob 都有边界。真正可靠的强制下载,应由服务端响应头驱动:
- 返回
Content-Disposition: attachment; filename="report.pdf",浏览器无论是否跨域、是否点击a[download],都会弹保存框 - 同时配
Content-Type: application/octet-stream避免被浏览器尝试解析(尤其对 txt/json/csv) - 如果后端是 Node.js(Express),加一行:
res.setHeader('Content-Disposition', 'attachment; filename="data.csv"'); - Nginx 可用
add_header Content-Disposition "attachment; filename=$arg_filename";动态注入
前端能做的只是触发请求,最终要不要下载、存成什么名,服务端才有决定权。别在 download 属性上死磕兼容性问题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











