这个问题在 若依(Vue3 + Axios)体系里是非常典型的,本质就是一句话:
后端返回的是 二进制流(stream) → 前端必须用 blob / arraybuffer 接收并手动处理
我给你按「实战级」讲清楚👇
一、前端怎么接收文件流(核心写法)
✅ 标准写法(若依推荐)
import request from "@/utils/request";
export function downloadFile(params) {
return request({
url: "/xxx/download",
method: "get",
params,
responseType: "blob", // ⚠️ 关键
});
}
👉 关键点:
responseType: 'blob':告诉 axios 这是二进制流- 返回值:
res里res.data就是文件流
二、拿到流之后怎么处理
✅ 场景1:直接下载文件(最常见)
downloadFile().then((res) => {
const blob = new Blob([res.data]);
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
// 文件名(推荐从后端拿)
link.download = "文件.xlsx";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
});
👉 原理:
- 后端返回 → 二进制流
- 前端转成 Blob
- 再生成一个 URL 下载 (阿里云开发者社区)
✅ 场景2:预览(图片 / PDF)
const blob = new Blob([res.data]);
const url = URL.createObjectURL(blob);
this.previewUrl = url;
用法:
<img :src="previewUrl" />
<!-- 或 -->
<iframe :src="previewUrl"></iframe>
✅ 场景3:转 base64(小程序/特殊需求)
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = () => {
const base64 = reader.result;
};
三、若依里更优雅的封装(推荐)
若依其实一般会封一个工具:
// utils/download.js
export function downloadBlob(data, filename) {
const blob = new Blob([data]);
const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = filename;
link.click();
}
使用:
downloadFile().then((res) => {
downloadBlob(res.data, "报表.xlsx");
});
四、文件名怎么动态获取(重点)
后端一般会这样返回:
Content-Disposition: attachment; filename=xxx.xlsx
前端拿:
const disposition = res.headers["content-disposition"];
const fileName = decodeURIComponent(disposition.split("filename=")[1]);
五、常见坑(若依项目一定会遇到)
❌ 1. 返回 JSON 错误但你用 blob 接收
👉 结果:下载了一个“错误文件”
解决:
const reader = new FileReader();
reader.onload = () => {
try {
const json = JSON.parse(reader.result);
console.error("接口报错", json);
} catch (e) {
// 正常文件
}
};
reader.readAsText(res.data);
❌ 2. axios 拦截器把 blob 搞没了
若依默认拦截器:
return response.data;
👉 会导致你拿不到 headers(文件名)
✅ 正确:
return response;
❌ 3. 小程序(uniapp)特殊点
如果你是在 uniapp(微信小程序):
不能用 Blob,要用:
uni.downloadFile({
url: "接口地址",
success: (res) => {
const tempFilePath = res.tempFilePath;
},
});
👉 小程序是走文件系统,不是浏览器 Blob
六、有哪些现成插件(直接可用)
1️⃣ file-saver(最推荐)
👉 浏览器下载标准库
npm install file-saver
import { saveAs } from "file-saver";
saveAs(new Blob([res.data]), "文件.xlsx");
优点:
- 兼容性好
- 写法简单
2️⃣ js-file-download
npm install js-file-download
import fileDownload from "js-file-download";
fileDownload(res.data, "文件.xlsx");
3️⃣ 若依自带 download 方法(最推荐你用这个)
若依里通常已经有:
this.$download(url, params, filename);
👉 内部已经帮你处理好了 blob
七、总结(给你一套标准认知)
你可以这样理解整个链路:
后端(流)
↓
axios(responseType=blob)
↓
res.data(二进制)
↓
Blob
↓
URL.createObjectURL
↓
下载 / 预览
如果你要更深入(建议你下一步问我)
你现在这个阶段,我建议你下一步可以搞:
👉 若依源码里 download.js 是怎么封装的 👉 uniapp + Vue2 怎么统一处理文件流(坑很多) 👉 流式接口(SSE)+ 文件混合返回(你项目正在用)
我可以帮你直接做一套「若依 + uniapp 通用下载方案」。