前端文件下载的 N 种姿势:从简单到高级
在 Web 开发中,文件下载是一个非常常见的功能。无论是下载用户生成的数据、图片、文档,还是应用程序包,前端开发者都有多种实现方式。本文将从最简单的方法讲起,逐步介绍到高级方案,并提供可运行的示例代码。
1. <a>
标签的 download
属性(最简单)
这是实现文件下载最直观的方法,尤其适用于下载静态资源或已知 URL 的文件。
原理
HTML5 为 <a>
标签新增了 download
属性。当用户点击带有 download
属性的链接时,浏览器会强制下载资源,而不是直接导航到它。你还可以为 download
属性指定一个值,作为推荐下载文件名。
示例
<a href="/files/sample.pdf" download="myFile.pdf">下载 PDF 文件</a>
优点
- 实现简单,无需 JavaScript
- 语义化好
- 兼容性好(现代浏览器支持)
缺点
- 同源限制:跨域资源可能无法下载,或者下载文件名不是预期值
- 动态内容:不适用于通过 API 获取或前端生成的文件
- 请求控制:无法添加自定义请求头(如 Authorization)
2. window.open()
或 window.location.href
这种方式本质上是导航到一个 URL。如果服务器在响应时设置了:
Content-Disposition: attachment; filename="filename.ext"
浏览器就会触发下载。
示例
// 使用 window.open
window.open('https://example.com/files/report.pdf');
// 使用 window.location.href(会替换当前页面)
window.location.href = 'https://example.com/files/report.pdf';
优点
- 实现简单
- 可以下载跨域文件(服务器需正确设置响应头)
缺点
- 文件名由服务器控制,前端无法直接指定
- 用户体验可能受影响:
window.location.href
会导致页面跳转,window.open
可能被弹窗拦截器阻止 - 不适用于前端生成的 Blob 数据下载
- 无法设置自定义请求头
3. Fetch API / XHR + Blob + URL.createObjectURL(高级方案)
这是最灵活的前端下载方式,尤其适合:
- 需要认证的 API 文件下载
- 前端生成数据(Canvas、JSON 等)
- 需要下载进度或自定义请求头
原理
- 使用 Fetch API 或 XMLHttpRequest 请求文件数据
- 将响应数据转换为
Blob
对象 - 使用
URL.createObjectURL(blob)
创建临时 URL - 创建隐藏
<a>
标签,设置href
为该 URL,并设置download
文件名 - 模拟点击
<a>
标签触发下载 - 下载完成后,调用
URL.revokeObjectURL(objectURL)
释放内存
示例(Fetch API)
async function downloadFile(url, filename) {
try {
const response = await fetch(url, {
headers: {
'Authorization': 'Bearer your-token'
}
});
if (!response.ok) throw new Error('下载失败');
const blob = await response.blob();
const objectURL = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = objectURL;
a.download = filename;
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(objectURL); // 释放内存
} catch (error) {
console.error('下载出错:', error);
}
}
// 调用示例
downloadFile('/api/files/report.pdf', 'report.pdf');
优点
- 完全控制:可以设置请求头、请求方法和请求体
- 支持动态数据:适合前端生成或 API 返回的二进制文件
- 错误处理:可精确捕获下载错误
- 进度控制:XHR 支持
progress
事件,可实现下载进度条
缺点
- 实现较复杂
- 需要手动管理 Blob 和 URL
- 内存管理需注意
revokeObjectURL
4. 总结:选择哪种方式
场景 | 推荐方式 | 说明 |
---|---|---|
静态文件、已知 URL | <a download> | 简单直接,无需 JS |
跨域下载、服务器控制文件名 | window.open 或 window.location.href | 文件名由服务器 Content-Disposition 决定 |
动态内容、需要认证或控制下载 | Fetch/XHR + Blob + URL.createObjectURL | 可自定义请求头,支持前端生成文件 |
理解这些方法的原理和适用场景,可以帮助你在不同下载需求中选择最合适的方案,同时兼顾用户体验和实现复杂度。
如果你需要,我可以再写一篇 完整前端示例 Demo,包含:
- 静态文件下载
- API 文件下载(带认证)
- 前端生成 JSON / CSV 文件下载