标签download属性仅对同源或cors允许的资源生效,跨域需fetch+blob+createobjecturl;服务端content-disposition响应头决定下载行为,drm或分片视频无法通过前端直接下载。

点击 <a></a> 标签直接触发下载,靠 download 属性
浏览器原生支持通过 <a></a> 标签下载文件,前提是目标资源同源(或服务端明确允许跨域),且使用 download 属性。它不是“发起请求”的逻辑,而是告诉浏览器:“这个链接点开不跳转,只保存”。
-
download属性值可选:留空(<a download href="xxx.pdf"></a>)表示用响应头Content-Disposition或 URL 路径推导文件名;填字符串(<a download="report.pdf" href="data.pdf"></a>)则强制指定保存名 - 跨域资源(比如 CDN 上的视频)即使加了
download,Chrome/Firefox 也会静默忽略——不报错,但点击后仍会跳转或播放,不会下载 - 常见错误:对
https://example.com/video.mp4直接加download就想下视频,结果在新标签页打开播放器。这是因为服务端没配Access-Control-Allow-Origin: *,浏览器拒绝触发下载行为
非同源资源下载必须走 fetch + Blob + URL.createObjectURL
当你要下载的是跨域文件(如公开的 YouTube 视频直链、S3 图片、第三方 API 返回的 PDF),唯一可靠路径是手动拉取二进制流,再构造本地可下载链接。
- 核心三步:
fetch(url)→response.blob()→URL.createObjectURL(blob),然后赋给<a download="xxx"></a>的href - 注意
fetch默认不带 CORS 头,如果目标服务器没开Access-Control-Allow-Origin,会直接失败并抛TypeError: Failed to fetch - 大文件(如 >100MB 视频)用这方案没问题,但别忘了调用
URL.revokeObjectURL()清理内存,否则 Blob URL 泄露会导致内存持续占用 - 示例片段:
fetch('https://cdn.example.com/movie.mp4') .then(r => r.blob()) .then(blob => { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'movie.mp4'; a.click(); URL.revokeObjectURL(url); // 关键,别漏 });
Content-Disposition: attachment 是服务端配合的关键响应头
前端加 download 或走 fetch 都只是“触发下载动作”,真正决定浏览器是否弹保存框、默认用什么文件名的,是服务端返回的 HTTP 响应头。
- 最有效的是服务端设置
Content-Disposition: attachment; filename="xxx.mp4",这样即使没有download属性,点击链接也会下载(但仅限同源) - 如果服务端只返回
Content-Type: video/mp4而没设Content-Disposition,浏览器大概率选择内联播放,而不是下载 - 某些 Nginx / Apache 配置里默认不加这个头,需要显式配置:Nginx 中用
add_header Content-Disposition "attachment";,Apache 用Header set Content-Disposition "attachment"
视频文件不能靠右键“另存为”?那得看是不是流式传输或 DRM
很多网页视频(尤其是在线教育、流媒体平台)根本无法通过常规方式下载,不是前端写法问题,而是服务端做了限制。
立即学习“前端免费学习笔记(深入)”;
- 用
HLS(.m3u8+.ts分片)或DASH(.mpd)协议播放的视频,源地址本身就是多个小文件,右键“另存为”只会保存播放列表,不是完整视频 - 带
DRM(如 Widevine、FairPlay)的视频,浏览器连原始音视频帧都拿不到,fetch到的也是加密数据,解密密钥由 CDM 模块管理,前端无权访问 - 所谓“下载视频攻略”,99% 是针对未加密、直链可访问的 MP4/AVI 等静态文件。一旦涉及分片、加密、动态 token 鉴权,就超出了 HTML 链接能解决的范围
download 属性和 fetch 都只是对着空气挥手。











