前端流式下载
1. 概述
在文件下载场景中,后端通常会将文件内容发送给前端,前端再将其保存为本地文件。常见的实现方式有两种:
base64编码下载:后端将文件内容编码为base64字符串,前端接收到后解码并保存为文件。- 流式下载:后端直接将文件内容以流的形式发送给前端,前端接收到后直接保存为文件。
本文将对比这两种方法的实现方式、性能和适用场景。
2. 原始代码(base64 编码下载)
2.1 后端接口
后端接口返回一个包含 base64 编码数据的 JSON 对象。
Node.js 示例:
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
const PORT = 3000;
app.get('/api/download', (req, res) => {
const filePath = path.join(__dirname, 'data/example.csv');
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
return res.status(500).send({ error: 'File not found' });
}
const base64Data = Buffer.from(data).toString('base64');
res.json({ resultData: base64Data });
});
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
2.2 前端代码
前端代码需要对返回的 base64 数据进行解码,并将其转换为文件。
const downloadFile = async (type) => {
try {
const { data } = await api.aaaGetResult({
aaa: route.params.aaa,
id: id.value,
fileType: type,
});
if (data && data.resultData) {
const decodedData = decodeURIComponent(escape(window.atob(data.resultData)));
const blob = new Blob([decodedData], {
type: "application/json",
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.style.display = "none";
a.href = url;
a.download = "aaa_result_0." + type; //
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
} catch (error) {
console.error("结果下载失败:", error);
}
};
3. 新代码(流式下载)
3.1 后端接口
后端接口直接返回文件流,而不是 base64 编码的数据。
Node.js 示例:
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
const PORT = 3000;
app.get('/api/download', (req, res) => {
const filePath = path.join(__dirname, 'data/example.csv');
// 设置响应头
res.setHeader('Content-Type', 'text/csv');
res.setHeader('Content-Disposition', 'attachment; filename="example.csv"');
// 读取文件并返回流
const stream = fs.createReadStream(filePath);
stream.pipe(res);
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
3.2 前端代码
前端代码直接处理返回的文件流,无需解码。
const downloadFile = async (type) => {
try {
const response = await api.aaaGetResult({
aaa: route.params.,
id: id.value,
fileType: type,
responseType: "blob" // 设置响应类型为 blob
});
// 检查响应状态
if (response.status === 200) {
// 创建一个 Blob 对象
const blob = new Blob([response.data], { type: "application/octet-stream" });
// 创建一个 URL 对象
const url = URL.createObjectURL(blob);
// 创建一个 a 标签用于下载
const a = document.createElement("a");
a.style.display = "none";
a.href = url;
a.download = `aaa_result_0.${type}`; // 设置下载文件名
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url); // 释放 URL 对象
} else {
ElMessage.error("下载失败,服务器返回错误");
}
} catch (error) {
console.error("结果下载失败:", error);
ElMessage.error("下载失败,请稍后重试");
}
};
4. 对比总结
4.1 数据格式
| 特性 | base64 编码下载 | 流式下载 |
|---|---|---|
| 后端返回格式 | base64 编码的字符串 | 直接返回文件流 |
| 前端处理 | 需要解码 base64 数据 | 直接处理文件流,无需解码 |
| 性能 | 数据量较大时效率低 | 数据量较大时效率高 |
| 安全性 | 数据在传输过程中被编码,可能增加复杂性 | 数据直接传输,减少中间处理步骤 |
| 易用性 | 需要额外的解码逻辑 | 简化了前端逻辑,直接处理文件 |
4.2 适用场景
-
base64编码下载:- 适用于数据量较小的场景。
- 适用于需要对数据进行额外处理的场景。
-
流式下载:
- 适用于数据量较大的文件。
- 适用于需要高效传输文件的场景。
- 适用于直接将文件保存到本地的场景。
5. 推荐使用流式下载
流式下载在处理大文件时具有显著的性能优势,并且简化了前端的处理逻辑。推荐在文件下载场景中优先使用流式下载。
1万+

被折叠的 条评论
为什么被折叠?



