在前端开发中,实现文件下载是常见的需求。根据不同的场景,我们可以选择不同的方法来实现文件流的下载。本文介绍三种常用的文件下载方式:
- 使用
axios
发送 JSON 请求下载文件流 - 使用
axios
发送FormData
请求下载文件流 - 使用原生
form
表单提交下载文件流
一、使用 Axios 下载文件流(JSON 格式参数)
✅ 适用场景:
适用于需要通过 POST 请求发送 JSON 数据给后端以获取文件流的情况。
⚠️ 注意事项:
- 设置
responseType: 'blob'
。 - 使用
Blob
对象处理响应数据。 - 动态获取文件名需依赖
Content-Disposition
头部字段,部分浏览器可能不支持,需服务器配置允许跨域访问该头部。
🧩 示例代码:
axios({url: 'https://localhost/download/test',method: 'post',data: {headers: ["姓名", "年龄", "城市"],data: [{"姓名": "张三","年龄": 25,"城市": "北京"}],fileName: "99"},responseType: 'blob',withCredentials: true
}).then(response => {// 获取文件名let filename = '默认文件.xlsx';const disposition = response.headers['content-disposition'];if (disposition && disposition.indexOf('filename=') !== -1) {filename = disposition.split('filename=')[1].replace(/"/g, '');try {filename = decodeURIComponent(filename);} catch (e) {filename = unescape(filename);}}// 创建 Blob 并触发下载const blob = new Blob([response.data], { type: response.headers['content-type'] });const url = window.URL.createObjectURL(blob);const link = document.createElement('a');link.href = url;link.download = filename;document.body.appendChild(link);link.click();window.URL.revokeObjectURL(url);document.body.removeChild(link);
});
二、使用 Axios 下载文件流(FormData 格式参数)
✅ 适用场景:
适用于需要传递键值对形式的数据(如上传文件)或模拟表单提交的场景。
⚠️ 注意事项:
- 设置请求头为
'application/x-www-form-urlencoded'
。 - 使用
FormData
构造请求体。 - 同样需要处理动态文件名。
🧩 示例代码:
const formData = new FormData();
formData.append("key", "value");axios({url: 'http://localhost/api/download',method: 'post',data: formData,headers: {'Content-Type': 'application/x-www-form-urlencoded'},responseType: 'blob',withCredentials: true
}).then(response => {const disposition = response.headers['content-disposition'];let filename = '默认文件.xlsx';if (disposition && disposition.includes('filename=')) {filename = disposition.split('filename=')[1].replace(/"/g, '');try {filename = decodeURIComponent(filename);} catch (e) {filename = unescape(filename);}}const blob = new Blob([response.data], { type: response.headers['content-type'] });const url = window.URL.createObjectURL(blob);const link = document.createElement('a');link.href = url;link.download = filename;document.body.appendChild(link);link.click();window.URL.revokeObjectURL(url);document.body.removeChild(link);
});
三、使用原生 Form 表单提交下载文件流
✅ 适用场景:
适用于不需要 JavaScript 控制、直接通过表单提交参数并由后端返回文件流的场景。
⚠️ 注意事项:
- 需要手动创建隐藏的
<form>
元素。 - 不适合处理 Blob 文件流(无法控制下载行为)。
- 不支持异步操作,页面会跳转。
🧩 示例代码:
const paraData = { id: 1212, name: '测试名' };
const formActionUrl = gateUrl + '/api/dictData/downloadDictDataList';const form = document.createElement('form');
form.style.display = 'none';
form.action = formActionUrl;
form.method = 'post';
form.enctype = 'application/x-www-form-urlencoded'; // 可选document.body.appendChild(form);for (let key in paraData) {if (paraData.hasOwnProperty(key)) {const input = document.createElement('input');input.type = 'hidden';input.name = key;input.value = paraData[key];form.appendChild(input);}
}form.submit(); // 提交表单
form.remove(); // 移除表单
✅ 总结对比
方法 | 是否支持 JSON | 是否支持文件下载 | 是否支持动态文件名 | 是否异步 | 是否推荐 |
---|---|---|---|---|---|
Axios + JSON | ✅ | ✅ | ✅(依赖响应头) | ✅ | ✅ 推荐 |
Axios + FormData | ❌(自动转换) | ✅ | ✅ | ✅ | ✅ 推荐 |
原生 Form | ❌ | ✅ | ❌ | ❌ | ⚠️ 视情况 |
🔁 补充建议
- 封装统一下载工具函数:将通用逻辑提取成工具函数,提高复用性。
- 兼容中文文件名:建议后端统一使用 UTF-8 编码文件名,避免前端解析困难。
- 错误处理增强:添加
.catch()
捕获异常并提示用户。 - 取消请求机制:对于大文件或长时间请求,可考虑加入取消功能(如
CancelToken
或AbortController
)。