如何用Node.js流处理大文件上传与下载?

如何用Node.js流处理大文件上传与下载?
最新回答
干净好听的昵称

2022-04-04 06:53:51

使用Node.js流处理大文件上传与下载的核心是通过分块传输数据,避免一次性加载整个文件到内存,从而防止内存溢出。以下是具体实现方法及关键代码示例:

一、大文件上传处理

核心思路:前端上传时,后端利用multer中间件分块暂存文件,再通过流式管道(pipe)将数据从临时文件写入目标位置,最后清理临时文件。

  1. 安装依赖

    npm install express multer
  2. 实现代码

    const express = require('express');const multer = require('multer');const fs = require('fs');const path = require('path');const app = express();const upload = multer({ dest: 'uploads/' }); // 临时存储目录app.post('/upload', upload.single('file'), (req, res) => { if (!req.file) { return res.status(400).send('未上传文件'); } const tempFilePath = req.file.path; const targetDir = './final'; if (!fs.existsSync(targetDir)) { fs.mkdirSync(targetDir, { recursive: true }); } const targetPath = path.join(targetDir, req.file.originalname); const readStream = fs.createReadStream(tempFilePath); const writeStream = fs.createWriteStream(targetPath); // 管道传输 + 错误处理 readStream.pipe(writeStream); writeStream.on('finish', () => { fs.unlinkSync(tempFilePath); // 删除临时文件 res.send('文件上传成功'); }); writeStream.on('error', (err) => { fs.unlinkSync(tempFilePath); // 出错时清理临时文件 console.error('写入失败:', err); res.status(500).send('上传失败'); });});app.listen(3000, () => console.log('服务启动'));

关键点

  • multer将文件分块暂存到uploads/目录,避免内存堆积。
  • fs.createReadStream和fs.createWriteStream通过pipe实现流式传输。
  • 监听finish和error事件确保资源释放。
二、大文件下载处理

核心思路:通过fs.createReadStream创建可读流,设置响应头后直接管道(pipe)到HTTP响应对象,实现分批传输。

  1. 实现代码app.get('/download/:filename', (req, res) => { const filename = req.params.filename; const filePath = path.join('./files', filename); // 检查文件是否存在 fs.access(filePath, fs.constants.F_OK, (err) => { if (err) { return res.status(404).send('文件不存在'); } // 设置响应头 res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.setHeader('Content-Type', 'application/octet-stream'); const readStream = fs.createReadStream(filePath); readStream.pipe(res); // 错误处理 readStream.on('error', (err) => { console.error('读取失败:', err); res.status(500).send('下载失败'); }); // 客户端提前断开连接时清理资源 res.on('close', () => { readStream.destroy(); }); });});

关键点

  • Content-Disposition响应头触发浏览器下载行为。
  • pipe直接将流数据发送到客户端,避免内存占用。
  • 监听error和close事件防止资源泄漏。
三、稳定性增强措施
  1. 错误处理

    上传/下载时监听流的error事件,记录日志并返回友好错误信息。

    示例:readStream.on('error', (err) => { console.error('流错误:', err); res.status(500).send('服务异常');});

  2. 资源释放

    客户端提前断开连接时(如取消下载),调用stream.destroy()终止流。

    示例:res.on('close', () => { readStream.destroy();});

  3. 临时文件清理

    上传完成后无论成功与否,均删除multer生成的临时文件。

    示例:writeStream.on('error', () => { fs.unlinkSync(tempFilePath); // 出错时清理});

四、总结
  • 上传流程:multer分块暂存 → 流式读取临时文件 → 管道写入目标位置 → 清理临时文件。
  • 下载流程:检查文件存在性 → 设置响应头 → 流式读取文件 → 管道发送到客户端 → 错误处理。
  • 优势:内存占用恒定,适合处理GB级文件,支持高并发场景。

通过以上方法,可高效、稳定地实现Node.js大文件上传与下载功能。