
直接用 <a> 标签下载视频行不行?
行,但只对同源、且服务端允许跨域的视频资源有效。浏览器会检查响应头里的 Content-Disposition,如果没设为 attachment,多数现代浏览器(Chrome/Firefox)会优先播放而非下载。
- 必须加
download属性,否则点击就播放:<a href="video.mp4" download="my-video.mp4">下载</a> - 跨域资源(比如 CDN 上的 mp4)加了
download也会失效,控制台报错:Failed to download resource: the server responded with a status of 403 (Forbidden)或直接忽略download - 某些服务器返回
Content-Type: video/mp4但没配 CORS 头,前端无法读取 blob,后续方案就走不通
fetch + Blob + URL.createObjectURL 下载跨域视频
这是绕过同源限制、真正能下 CDN 视频的通用做法,核心是把视频二进制流转成本地可访问的 blob URL。
- 服务端需支持 CORS,至少返回
Access-Control-Allow-Origin: *,否则fetch直接被拦在预检阶段 - 务必用
response.arrayBuffer()(不是response.blob()),避免大视频内存暴涨;arrayBuffer()更底层、可控性强 - 生成 blob 后立即调用
URL.revokeObjectURL,不然内存泄漏——尤其用户反复点下载时
fetch('https://cdn.example.com/video.mp4')
.then(r => r.arrayBuffer())
.then(buf => {
const blob = new Blob([buf], { type: 'video/mp4' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'video.mp4';
a.click();
URL.revokeObjectURL(url); // 关键!
});
遇到 net::ERR_FAILED 或下载文件损坏怎么办?
这不是前端代码写错了,而是请求链路某处中断或截断,常见于服务端配置或网络中间件。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 检查响应状态码是否为
206 Partial Content:有些视频服务启用了分块传输(Range 请求),但前端没处理分块逻辑,直接拼整个 body 就会丢数据 - 确认服务端是否压缩了响应(如 gzip):Blob 构造时若类型写错(比如写成
text/plain),解压失败导致文件打不开 - 大视频(>500MB)建议加 loading 状态和取消机制,
fetch不支持原生 abort?那就用AbortController配合 signal
移动端 Safari 能不能下?
不能直接触发下载。iOS Safari 禁止 JS 创建的 a.click() 触发下载行为,哪怕用户刚点过一个真实按钮也不行。
立即学习“前端免费学习笔记(深入)”;
- 唯一可靠方式:引导用户长按链接,手动“保存视频”——所以
<a>标签仍要保留,作为降级入口 - 不要试图用
window.open(blobUrl),Safari 会打开空白页并立即关闭 - 如果页面本身是 PWA,可尝试用
beforeinstallprompt提示安装后调用文件系统 API,但兼容性极差,目前不现实
最麻烦的其实是服务端配合:没有 CORS、不支持 Range、强制跳转、加了防盗链 referer 检查……这些都得后端开白名单或改策略,前端再怎么绕也白搭。

















