Angular文件上传速度远慢于Postman,大文件上传易中断
解决Angular上传大文件到Node.js API慢且中断的问题
1. Angular请求配置调优
- 关掉默认的进度监听:Angular的HttpClient默认会频繁触发上传进度事件,过多事件会拖慢上传速度。如果不需要进度显示,直接将
reportProgress设为false:const formData = new FormData(); formData.append('video', file); this.http.post('/api/upload', formData, { reportProgress: false, responseType: 'json' }).subscribe(...); - 加长超时时间:大文件上传耗时久,默认超时限制可能不够,给请求设置5分钟超时:
import { timeout } from 'rxjs/operators'; this.http.post('/api/upload', formData) .pipe(timeout(300000)) // 300秒=5分钟 .subscribe(...);
2. Node.js后端参数调整
- 放开文件大小限制:不管用
multer还是express-fileupload,默认都有文件大小上限,手动设置成大于700MB的值:
用multer的配置:
用express-fileupload的配置:const multer = require('multer'); const upload = multer({ dest: './uploads/', limits: { fileSize: 800 * 1024 * 1024 // 设置800MB上限 } });app.use(fileUpload({ limits: { fileSize: 800 * 1024 * 1024 }, useTempFiles: true // 使用临时文件,减少内存占用 })); - 加长服务器超时:Node/Express默认请求超时较短,给请求和响应都设置5分钟超时:
app.use((req, res, next) => { req.setTimeout(300000); res.setTimeout(300000); next(); }); - 关闭冗余中间件:比如开发环境的morgan日志中间件,频繁打印日志会拖慢大文件上传速度,要么调整日志级别,要么直接关闭。
3. 跨域与网络排查
- 确认CORS配置:后端CORS要允许
multipart/form-data类型,不要限制过严。示例配置:const cors = require('cors'); app.use(cors({ origin: 'http://你的Angular域名', allowedHeaders: ['Content-Type'], methods: ['POST'] })); - 检查浏览器与网络:查看浏览器控制台是否有
net::ERR_CONNECTION_RESET这类错误,可能是浏览器本身超时限制,或者网络中存在防火墙/代理拦截大文件上传。
4. 分块上传兜底方案
如果上述方法都无效,试试分块上传,将700MB文件切成10MB左右的小块分多次上传,避免单次请求过大导致中断:
- Angular端分块处理代码:
async uploadFileInChunks(file: File) { const chunkSize = 10 * 1024 * 1024; // 10MB每块 const totalChunks = Math.ceil(file.size / chunkSize); for (let i = 0; i < totalChunks; i++) { const start = i * chunkSize; const end = Math.min(start + chunkSize, file.size); const chunk = file.slice(start, end); const formData = new FormData(); formData.append('chunk', chunk); formData.append('chunkIndex', i.toString()); formData.append('totalChunks', totalChunks.toString()); formData.append('fileName', file.name); await this.http.post('/api/upload-chunk', formData).toPromise(); } // 最后通知后端合并所有分块 await this.http.post('/api/merge-chunks', { fileName: file.name }).toPromise(); } - Node.js后端处理分块与合并:
const fs = require('fs'); const path = require('path'); app.post('/api/upload-chunk', upload.single('chunk'), (req, res) => { const { chunkIndex, totalChunks, fileName } = req.body; const tempDir = './temp-uploads'; if (!fs.existsSync(tempDir)) fs.mkdirSync(tempDir); const chunkPath = path.join(tempDir, `${fileName}.chunk${chunkIndex}`); fs.copyFileSync(req.file.path, chunkPath); fs.unlinkSync(req.file.path); // 删除multer生成的临时文件 res.sendStatus(200); }); app.post('/api/merge-chunks', (req, res) => { const { fileName } = req.body; const tempDir = './temp-uploads'; const outputPath = path.join('./uploads', fileName); const writeStream = fs.createWriteStream(outputPath); const chunkFiles = fs.readdirSync(tempDir).filter(f => f.startsWith(`${fileName}.chunk`)); const totalChunks = chunkFiles.length; for (let i = 0; i < totalChunks; i++) { const chunkPath = path.join(tempDir, `${fileName}.chunk${i}`); const readStream = fs.createReadStream(chunkPath); readStream.pipe(writeStream, { end: false }); readStream.on('end', () => { fs.unlinkSync(chunkPath); if (i === totalChunks - 1) { writeStream.end(); res.sendStatus(200); } }); } });
内容的提问来源于stack exchange,提问作者Akshay
相关产品推荐
相关产品推荐

