download属性仅对同源URL生效,跨域时失效;其值决定下载文件名,但不可含路径字符;iOS Safari完全不支持,需降级提示或服务端配合响应头。

download 属性只对同源 URL 生效
点击 <a> 标签触发下载,靠的是 download 属性,但它有个硬性限制:**只有同源的 URL 才能触发浏览器下载,跨域链接即使写了 download 也会直接跳转或打开,不会下载**。
常见误判场景:
- 本地开发时用
file://协议打开 HTML —— 此时所有相对路径都算“同源”,download看似可用,但上线后必失效 - 引用 CDN 上的 PDF 或 ZIP(如
https://cdn.example.com/report.pdf)—— 跨域,download被忽略,浏览器按默认行为处理(通常是新标签页打开) - 后端接口返回文件流(如
/api/export?format=csv)—— 接口地址和当前页面不同源,download无效
验证是否生效最简单的方法:右键链接 → “另存为”,如果弹出保存对话框,说明 download 起作用了;如果直接跳转或打开新页,就是被浏览器忽略了。
download 属性值不是必须填,但填了会影响文件名
download 是个可选属性,不写值(<a download>)或写空字符串(<a download="">)时,浏览器会尝试从 URL 路径中提取文件名(如 https://site.com/data.xlsx → 保存为 data.xlsx)。
立即学习“前端免费学习笔记(深入)”;
但如果显式指定值,比如 <a href="report.php" download="月度统计.xlsx">,浏览器就用这个字符串当默认保存名,**哪怕原始 URL 根本不带扩展名或路径是动态的**。
注意点:
- 值中不能含路径字符(如
/、\),否则整个download属性会被浏览器静默丢弃 - 中文名一般没问题(现代浏览器都支持 UTF-8 文件名),但旧版 Safari 可能截断或乱码,稳妥起见建议用英文+下划线
- 如果 href 是 blob URL(如
blob:https://…),download值是唯一决定保存名的方式,URL 本身不提供文件名
非同源文件下载得绕开 download 属性
遇到跨域资源或接口流,download 属性形同虚设,得换方案。主流做法是用 JavaScript 触发下载:
- 对 CORS 允许的资源,用
fetch拿到blob,再用URL.createObjectURL创建本地 blob URL,最后用带download的<a>触发 - 对普通跨域链接(如 CDN 上的 zip),只能引导用户右键“另存为”,或者服务端加
Content-Disposition: attachment; filename=xxx.zip响应头(需后端配合) - 表单提交也能触发下载(
<form method="GET" action="/export.csv">),适合简单导出,但无法自定义文件名,且不支持 POST 参数复杂场景
小技巧:用 fetch + blob 方案时,记得调用 URL.revokeObjectURL 清理内存,尤其在频繁下载时。
移动端 Safari 对 download 属性支持极差
iOS/iPadOS 的 Safari 完全不支持 download 属性,无论同源与否,点了就跳转或打不开。这是硬伤,没绕过办法。
实际应对策略:
- 检测
navigator.userAgent是否含iPhone/iPad/Macintosh.*Safari,是则隐藏下载按钮,改提示“请长按链接 → ‘下载链接中的文件’” - 用
iframesrc 指向文件 URL(如<iframe src="/file.pdf" style="display:none"></iframe>),部分 iOS 版本能触发下载提示(不稳定,仅作保底) - 真正可靠的方案仍是后端直出,通过响应头强制下载,并确保链接可被长按识别
别指望 polyfill 或 JS 模拟 —— 浏览器权限模型决定了前端无法在无用户手势前提下自动保存文件到设备存储,这点在 iOS 上卡得死死的。



















