download属性仅对同源URL生效,跨域需用fetch+Blob方案;同源指协议、域名、端口全一致;data:和blob: URL可下载但有兼容性限制;服务端须设置Content-Disposition响应头。

download 属性只对同源 URL 生效
直接给 <a> 标签加 download 属性,浏览器并不会无条件触发下载——它只对同源的 href 值起作用。比如你页面在 https://example.com,而 href 指向 https://cdn.example.com/file.pdf(子域不同)或 https://other-site.com/data.csv(跨域),此时 download 会被忽略,点击后直接在新标签页打开文件。
常见错误现象:download 属性存在但点击后不下载、跳转或报错 Failed to download file: Not allowed to navigate top frame to data URL(尤其在 iframe 或 sandbox 环境中)。
- 同源判断依据是协议 + 域名 + 端口,三者必须完全一致
-
href为data:URL 时,download可用,但部分旧版 Chrome 会静默失败 -
blob:URL 需配合URL.createObjectURL()生成,且必须同源(即 blob 由当前页面 JS 创建)
如何安全触发跨域文件下载
遇到 CDN、API 接口返回的文件流(如 /api/export?format=csv),不能靠 <a download="report.csv" href="https://cdn.com/xxx.csv"> 解决。必须走 JS 控制的二进制流处理路径。
核心思路:用 fetch 获取响应体 → 转为 Blob → 创建本地 blob: URL → 触发 <a> 下载。
立即学习“前端免费学习笔记(深入)”;
- 务必设置
response.blob(),而非response.text(),否则中文文件名或二进制内容会损坏 - 从
Content-Disposition响应头读取建议文件名(需服务端开启 CORS 共享该 header):res.headers.get('content-disposition') - 若服务端未返回文件名,fallback 到手动指定:
const filename = 'export.csv'
fetch('/api/export?format=csv')
.then(res => res.blob())
.then(blob => {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'report.csv'; // 手动指定,或从 header 解析
a.click();
URL.revokeObjectURL(url); // 用完立即释放,避免内存泄漏
});
download 属性值为空字符串或未设时的行为
<a download href="doc.pdf">下载</a> 和 <a download="" href="doc.pdf">下载</a> 效果一致:浏览器会尝试从 href 的 URL 路径中提取文件名(如 https://x.com/a/b/c.pdf → c.pdf)。但若 URL 是纯路径无扩展名(如 /api/download?id=123),则可能保存为无后缀的乱码文件或默认叫 download。
- 显式写
download="invoice-2024.pdf"是最稳妥的做法,能控制最终保存名 - 注意:文件名中不要含
/、\、:等非法字符,否则部分浏览器会截断或报错 - Safari 对
download支持较弱(尤其 iOS),即使同源也可能拒绝下载,需降级为新开窗口 + 提示用户右键另存
服务端需配合的细节容易被忽略
前端加了 download,不代表一定能下。服务端响应头必须配合,否则浏览器可能按 MIME 类型决定是下载还是渲染。
- 关键响应头:
Content-Disposition: attachment; filename="xxx.pdf"(强制下载) - 避免返回
Content-Type: text/html或application/json,即使文件是 PDF;应返回真实类型,如application/pdf、text/csv - 如果接口需要鉴权(如带 Cookie 或 Bearer Token),
fetch必须加credentials: 'include'或headers: { Authorization: '...' },否则 401 - 大文件下载时,服务端别超时,前端也建议加 loading 状态,避免用户重复点击生成多个
blob:URL
真正卡住的往往不是 download 属性本身,而是同源限制、响应头缺失、Blob 处理不当这三点中的某一个。先检查 Network 面板里请求是否成功、响应头是否含 Content-Disposition、控制台有无 CORS 报错,比反复改 HTML 更有效。


















