html5 标签无原生下载功能,下载需获取真实视频url并用js触发;跨域需后端cors支持,ios safari不支持download属性,常见失败源于签名过期、cors拦截或平台限制。

HTML5 <video></video> 标签本身不支持“下载”功能
浏览器原生 <video></video> 播放器没有内置下载按钮,也**不会自动提供下载入口**——这是刻意设计的安全与版权限制。所谓“用 HTML5 下载视频”,实际是绕过播放器、直接请求视频资源文件。
用户点击下载时,本质是发起一次 fetch 或 XMLHttpRequest 请求
必须拿到视频的真实 URL(非 m3u8、非 dash 清单,而是 mp4/webm 等可直接下载的二进制地址),然后用 JS 触发下载。常见错误是误把 src 属性值当下载地址,结果 403 或 404:
- 视频源是 CDN 链接且带签名(如
https://xxx.mp4?Expires=123&OSSAccessKeyId-abc&Signature=xyz),过期即失效 - 服务器设置了
Referrer-Policy或CORS,导致 JS 无法跨域 fetch - 后端返回了
Content-Disposition: inline,浏览器默认播放而非下载
实操建议:
- 先在开发者工具 Network 面板里找到 type 为
media的请求,右键 Copy → Copy link address,确认该链接能单独在新标签页打开并播放 - 用
fetch(url, { mode: 'no-cors' })仅适用于同源;跨域必须后端配合加Access-Control-Allow-Origin - 下载逻辑推荐用
URL.createObjectURL()+<a download="xxx.mp4"></a>点击后仍会跳转播放,不会下载。解决路径只有两条:
立即学习“前端免费学习笔记(深入)”;
- 后端代理:用自己域名下的接口(如
a[download])返回视频流,并设置<a href="https://cdn.example.com/vid.mp4" download="demo.mp4">下载</a> - 前端 fetch + blob:获取响应后生成 blob URL,再触发
/api/proxy?url=https%3A%2F%2Fcdn.example.com%2Fvid.mp4,但要求服务端允许 CORS(否则 fetch 失败)
示例关键片段:
fetch(videoUrl) .then(r => r.blob()) .then(blob => { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'video.mp4'; a.click(); URL.revokeObjectURL(url); // 记得释放 });移动端 Safari 对
Content-Disposition: attachment; filename="xxx.mp4"属性完全忽略iOS/iPadOS 所有版本的 Safari 都不支持
a[download],点击只会尝试播放或提示“无法下载”。没有兼容方案,JS 生成的 blob URL 同样无效。能做的只有:
- 检测
download,对 iOS 用户隐藏下载按钮 - 引导用户长按视频画面 → “保存视频”(仅限部分网页内嵌 video 且服务端未禁用)
- 如果视频来自自己的服务,考虑在服务器端生成带 token 的直链,并用
a[download]跳转——Safari 会触发下载对话框(但需后端设置正确 header)
- 后端代理:用自己域名下的接口(如











