前端文件下载常用方式详解

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

  • 使用 axios 发送 JSON 请求下载文件流
  • 使用 axios 发送 FormData 请求下载文件流
  • 使用原生 form 表单提交下载文件流

一、使用 Axios 下载文件流(JSON 格式参数)

✅ 适用场景:

适用于需要通过 POST 请求发送 JSON 数据给后端以获取文件流的情况。

⚠️ 注意事项:

  • 设置 responseType: 'blob'
  • 使用 Blob 对象处理响应数据。
  • 动态获取文件名需依赖 Content-Disposition 头部字段,部分浏览器可能不支持,需服务器配置允许跨域访问该头部。

🧩 示例代码:

javascript 复制代码
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 构造请求体。
  • 同样需要处理动态文件名。

🧩 示例代码:

javascript 复制代码
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 文件流(无法控制下载行为)。
  • 不支持异步操作,页面会跳转。

🧩 示例代码:

javascript 复制代码
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 ⚠️ 视情况

🔁 补充建议

  1. 封装统一下载工具函数:将通用逻辑提取成工具函数,提高复用性。
  2. 兼容中文文件名:建议后端统一使用 UTF-8 编码文件名,避免前端解析困难。
  3. 错误处理增强 :添加 .catch() 捕获异常并提示用户。
  4. 取消请求机制 :对于大文件或长时间请求,可考虑加入取消功能(如 CancelTokenAbortController)。
相关推荐
wordbaby20 小时前
TanStack Router 实战:如何优雅地实现后台管理系统的“多页签” (TabList) 功能
前端·react.js
凌览20 小时前
2026年1月编程语言排行榜|C#拿下年度语言,Python稳居第一
前端·后端·程序员
user861581857815421 小时前
Element UI 表格 show-overflow-tooltip 长文本导致闪烁的根本原因与解法
前端
不会写前端的小丁21 小时前
前端首屏渲染性能优化小技巧
前端
还不秃顶的计科生21 小时前
defaultdict讲解
开发语言·javascript·ecmascript
晴虹21 小时前
lecen:一个更好的开源可视化系统搭建项目--组件和功能按钮的权限控制--全低代码|所见即所得|利用可视化设计器构建你的应用系统-做一
前端·后端·低代码
爱分享的鱼鱼21 小时前
Pinia 深度解析:现代Vue应用状态管理最佳实践
前端·后端
花归去21 小时前
echarts 柱状图包含右侧进度
开发语言·前端·javascript
沐浴露z21 小时前
学习通“只能录入不能粘贴” 解决方案与原理分析
javascript
多看书少吃饭21 小时前
Vite开发环境按需编译是怎么实现的
前端