前端如何通过 Blob 下载 Excel 文件

后端接口返回 Blob 数据流下载 Excel 文件流程

📌 前提条件:

  • 后端返回的是一个 Excel 文件流(Blob)
  • 你的接口请求使用了 axios

🔁 步骤 1:设置请求响应类型为 Blob

在发起请求时,配置 responseType: 'blob',确保后端返回的数据以二进制流形式接收。示例(以 Axios 为例):

javascript 复制代码
axios.get('/api/download-excel', {
  params: {},
  responseType: 'blob'
})

🧾 步骤 2: 将响应数据转换为 Blob 对象

接收到响应后,用 new Blob() 封装二进制数据,并指定文件类型为 Excel 格式:

javascript 复制代码
const blob = new Blob([res.data], {
  type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
  • res.data:就是后端返回的原始二进制数据
  • type:指定为 Excel 的 MIME 类型(推荐)

🔗步骤 3:创建临时下载链接

通过 URL.createObjectURL() 创建指向 Blob 的临时链接:

javascript 复制代码
const downloadUrl = window.URL.createObjectURL(blob);

这个链接是浏览器内部生成的,不会真正请求服务器。

📥 步骤 4:创建 <a> 标签并模拟点击

动态生成 <a> 标签,设置 href 为临时链接,添加 download 属性指定文件名,并模拟点击:

javascript 复制代码
const link = document.createElement('a');
link.href = downloadUrl;
link.download = 'data.xlsx';
document.body.appendChild(link);
link.click();

🧹步骤 5 & 6:清理内存中的对象 URL 和移除 <a> 标签

使用 URL.revokeObjectURL() 清理内存,避免资源泄漏:

javascript 复制代码
window.URL.revokeObjectURL(downloadUrl); // 清理对象 URL
document.body.removeChild(link); // 移除 <a> 标签

完整代码示例

javascript 复制代码
axios.get('/api/download-excel', {
  params: {},
  responseType: 'blob'
}).then(res => {
  const blob = new Blob([res.data], {
    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  });
  const downloadUrl = window.URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = downloadUrl;
  link.download = 'data.xlsx';
  document.body.appendChild(link);
  link.click();
  window.URL.revokeObjectURL(downloadUrl);
  document.body.removeChild(link);
});

🧪 补充说明:如何从响应头获取文件名?

有些后端会在响应头里返回文件名,例如:

javascript 复制代码
Content-Disposition: attachment; filename="预充值记录-20240710.xlsx"

你可以提取出来作为下载文件名:

javascript 复制代码
const disposition = res.headers['content-disposition'];
let filename = '预充值记录.xlsx';

if (disposition && disposition.indexOf('filename=') !== -1) {
    const matches = /filename="?([^"]+)"?/.exec(disposition);
    if (matches.length > 1) {
        filename = decodeURIComponent(matches[1]);
    }
}

然后传给 download 属性:

javascript 复制代码
link.setAttribute('download', filename);

🛠 如果你想统一封装一个下载函数(推荐)

你可以写一个通用函数来处理下载:

javascript 复制代码
function downloadFile(url, method = 'get', data = {}, filename = '文件.xlsx') {
    return sendPost(url, data, method, {}, {}, {
        responseType: 'blob'
    }).then(res => {
        const blob = new Blob([res.data]);
        const downloadUrl = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = downloadUrl;
        link.setAttribute('download', filename);
        document.body.appendChild(link);
        link.click();
        window.URL.revokeObjectURL(downloadUrl);
        document.body.removeChild(link);
    });
}

使用示例:

javascript 复制代码
downloadFile('/user/user/prepay/log', 'get', {
    created_time_start: '2024-07-01',
    created_time_end: '2024-07-10',
    excel: true
}, '预充值记录.xlsx');

🚫 常见错误排查

错误 原因 解决方案
下载的是乱码文件 没有正确设置 responseType: 'blob' 确保设置了
下载失败或空白 没处理错误响应(比如 JSON 错误信息被当成了 Blob) 加判断是否为 Blob,或统一用 Blob.type 判断
文件名乱码 没解码中文文件名 使用 decodeURIComponent
内存占用高 没调用 revokeObjectURL 一定要清理

✅ 总结:完整流程图

步骤 说明
1️⃣ responseType: 'blob' 请求时配置,接收二进制数据
2️⃣ new Blob([res.data]) 创建 Blob 对象
3️⃣ URL.createObjectURL(blob) 创建临时下载链接
4️⃣ 创建 <a> 标签并点击 触发浏览器下载行为
5️⃣ URL.revokeObjectURL() 清理内存
6️⃣ removeChild(link) 移除动态创建的标签
相关推荐
修己xj2 分钟前
打造专属博文封面神器:一个开源免费的博文封面生成器ThisCover
前端
kyriewen5 分钟前
面试8家前端岗位后,我发现了一个残酷的事实:AI不是加分项,是门槛
前端·javascript·面试
Fighting_p23 分钟前
【面试 - el-select问题及解决】wujie 微前端下子系统 el-select 多选 filterable 过滤失效
前端
吃口巧乐兹24 分钟前
AI 全栈时代,为什么要服务端使用 NestJs
前端
yingyima28 分钟前
Redis 延迟任务队列:凌晨3点服务器报警的救星
前端
weiggle30 分钟前
第三篇:可组合函数(Composable)——Compose 的基石
android·前端
前端环境观察室32 分钟前
别只看 task success:AI Agent 浏览器自动化真正要补的是环境证据链
前端·后端
huakoh33 分钟前
LangChain 实战:用混合检索啃下 1000 页 PDF,搭一个长文档问答 Agent
前端
Dazer00742 分钟前
Edge 浏览器绕过 HTTPS 证书错误
前端·https·edge
元让_vincent1 小时前
Spark 2.0:面向 Web 的 3DGS 可视化与大场景渲染平台详解
前端·3d·spark·渲染·轻量化·3dgs·lod