download属性仅在同源静态资源下生效,需协议、域名、端口完全一致;跨域、动态接口、file://协议均无效;iOS Safari不支持,服务端Content-Disposition响应头优先级更高。

同源静态资源路径必须绝对精确
只有当 href 指向的路径满足同源(协议 + 域名 + 端口完全一致)且为可访问的静态文件时,download 属性才真正起作用。比如页面在 https://example.com/app/,那么 href="/assets/report.pdf" 或 href="./data.csv" 可以生效;但 href="https://cdn.example.com/file.xlsx"(子域不同)、href="/api/export"(动态接口)或 href="file:///local/test.txt"(file:// 协议)都会被浏览器静默忽略 download。
常见错误现象:点击链接后跳转到新页面、PDF 在线预览、控制台出现 download attribute has no effect on cross-origin links 警告——这说明浏览器压根没走下载流程。
-
download值中的斜杠会被截断,download="path/to/name.pdf"最终只取name.pdf - 含非法字符(如
/、\、:)会导致整个属性失效,不报错但无效 - 本地双击 HTML 文件(
file://协议)下该属性基本不可用,必须启动本地服务(如npx serve)
download 属性不是“强制开关”,而是“提示信号”
它本身不触发下载,只是告诉浏览器:“这个资源应该被保存”。是否执行,取决于三件事:资源是否同源、服务端是否返回 Content-Disposition: inline(会覆盖 download)、浏览器是否支持该行为。
iOS/iPadOS 全系 Safari 完全不支持 download,点同源链接也会打开预览;旧版 Edge 也有兼容问题。对 ZIP、EXE 等浏览器无法渲染的类型,download 属性加不加效果一样,浏览器默认就下载。
- 服务端返回
Content-Disposition: attachment; filename="report.pdf"时,download属性可省略,且更可靠 - 若服务端返回
Content-Disposition: inline,哪怕同源 + 正确download,也会被强制在线打开 - 文件类型可被渲染(如 PDF、PNG、TXT)时,
download才有“覆盖权”;不可渲染类型无此限制
动态创建 a 标签时顺序和清理不能省
用 JavaScript 动态创建下载链接时,href 必须先赋值,再设 download,否则 Safari 和部分 Chrome 版本会静默失败(不报错,但点击无反应)。
生成的 blob: URL 必须配合 URL.revokeObjectURL() 主动释放,否则内存持续增长;且 a 元素需挂载到 document.body 才能触发 click()(某些环境不挂载会拦截)。
- 错误写法:
a.setAttribute('download', 'name.pdf'); a.href = '/data.json';—— 部分浏览器丢弃download - 正确顺序:
a.href = '/data.json'; a.download = 'data.json'; - 务必调用
URL.revokeObjectURL(url),哪怕只下载一次 - 避免在 iframe 或 sandbox 环境中使用,可能触发
Not allowed to navigate top frame to data URL
跨域或动态接口必须绕过 download 属性限制
CDN 文件、API 导出接口、Canvas 导出图等场景,download 属性完全无效,唯一可靠路径是:fetch → blob → URL.createObjectURL() → 动态 a 标签 → click → revoke。
注意 MIME type 要匹配内容,比如 CSV 应用 "text/csv;charset=utf-8",否则 Excel 可能乱码;从响应头读取 Content-Disposition 获取真实文件名需服务端开启 CORS 共享该 header(Access-Control-Expose-Headers: Content-Disposition)。
- 不要用
response.text()再转 Blob,二进制内容(如 PDF)会损坏,必须用response.blob() - 服务端未返回文件名时,fallback 到手动指定,如
a.download = 'export-' + Date.now() + '.csv' - iOS Safari 不支持脚本触发下载,此时只能靠服务端设置
Content-Disposition响应头
download 属性。

















