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

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

  • 使用 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)。
相关推荐
OEC小胖胖1 小时前
去中心化身份:2025年Web3身份验证系统开发实践
前端·web3·去中心化·区块链
Cacciatore->2 小时前
Electron 快速上手
javascript·arcgis·electron
vvilkim2 小时前
Electron 进程间通信(IPC)深度优化指南
前端·javascript·electron
某公司摸鱼前端3 小时前
ES13(ES2022)新特性整理
javascript·ecmascript·es13
ai小鬼头4 小时前
百度秒搭发布:无代码编程如何让普通人轻松打造AI应用?
前端·后端·github
漂流瓶jz4 小时前
清除浮动/避开margin折叠:前端CSS中BFC的特点与限制
前端·css·面试
前端 贾公子4 小时前
在移动端使用 Tailwind CSS (uniapp)
前端·uni-app
散步去海边4 小时前
Cursor 进阶使用教程
前端·ai编程·cursor
清幽竹客4 小时前
vue-30(理解 Nuxt.js 目录结构)
前端·javascript·vue.js
weiweiweb8884 小时前
cesium加载Draco几何压缩数据
前端·javascript·vue.js