在前端开发中,实现文件下载是常见的需求。根据不同的场景,我们可以选择不同的方法来实现文件流的下载。本文介绍三种常用的文件下载方式:
- 使用
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
)。