💡 前端如何优雅下载100G大文件?Node.js流式传输实战
今天给大家分享一个前端下载超大文件的解决方案!工作中遇到需要下载100G大文件的场景,传统下载方式直接崩溃?来看看这个流式传输方案👇
🌟 核心思路
- 点击按钮先获取下载令牌(token)
- 通过a标签携带token访问下载接口
- 服务端使用流式传输(Stream)返回文件
- 前端边接收边保存,内存占用极低
🛠️ 前端实现
javascript
// 下载按钮点击事件
document.getElementById('downloadBtn').addEventListener('click', async () => {
try {
// 1. 获取下载token
const res = await fetch('/api/getDownloadToken', {
method: 'POST',
body: JSON.stringify({ filename: 'huge-file.zip' })
});
const { token } = await res.json();
// 2. 创建隐藏的a标签触发下载
const a = document.createElement('a');
a.href = `/api/download?token=${token}`;
a.download = 'huge-file.zip';
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
console.log('下载已开始,请稍候...');
} catch (err) {
console.error('下载失败:', err);
}
});
🔧 Node.js服务端代码
javascript
const express = require('express');
const fs = require('fs');
const crypto = require('crypto');
const app = express();
// 临时存储token和文件路径的映射
const tokenMap = new Map();
app.use(express.json());
// 生成下载token
app.post('/api/getDownloadToken', (req, res) => {
const { filename } = req.body;
const filePath = `/data/${filename}`; // 大文件实际路径
if (!fs.existsSync(filePath)) {
return res.status(404).json({ error: '文件不存在' });
}
// 生成唯一token
const token = crypto.randomBytes(16).toString('hex');
tokenMap.set(token, filePath);
// token有效期10分钟
setTimeout(() => tokenMap.delete(token), 600000);
res.json({ token });
});
// 流式下载文件
app.get('/api/download', (req, res) => {
const { token } = req.query;
const filePath = tokenMap.get(token);
if (!filePath) {
return res.status(403).send('无效或过期的token');
}
// 获取文件信息
const stat = fs.statSync(filePath);
const fileSize = stat.size;
const fileName = path.basename(filePath);
// 设置响应头
res.setHeader('Content-Disposition', `attachment; filename=${fileName}`);
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Length', fileSize);
// 创建可读流并管道传输到响应
const fileStream = fs.createReadStream(filePath);
fileStream.pipe(res);
// 清理token
tokenMap.delete(token);
});
app.listen(3000, () => console.log('服务器运行中...'));
✨ 方案优势
- 内存友好:流式传输不占用大内存
- 断点续传:可通过Range头实现(进阶功能)
- 安全可控:token机制防止未授权下载
- 进度显示:前端可通过xhr监听进度(代码略)
💡 进阶优化
- 添加下载进度条
- 实现断点续传功能
- 文件校验(MD5/SHA256)
- 下载限速控制
这个方案完美解决了我们公司处理超大文件下载的痛点!大家有什么问题欢迎评论区交流~ #前端开发 #Nodejs #文件下载 #编程技巧 #web开发