Node.js文件上传中间件阻塞求助:文件已保存但请求无法推进
Node.js + Express + multiparty 文件上传问题解决方案
问题描述
- 文件已成功保存到
uploads目录,但请求无法从上传中间件进入后续路由处理函数 - 若将
next()移到form.parse回调外部,请求可推进但req.body中无文件数据
问题原因
req.body未初始化导致报错:Express的req.body默认值为undefined,直接执行req.body.uploadedFile = uploadedFile会抛出TypeError,中断回调内代码执行,导致next()无法被调用- 若将
next()放在form.parse外部,会在multiparty完成文件解析前就推进请求,此时文件数据尚未写入req.body,因此后续路由无法获取数据
解决方案
1. 修复中间件中的req.body初始化问题
修改uploadFileMiddleware,在给req.body赋值前先初始化对象:
// fileUpload.ts import multiparty from 'multiparty'; import { Request, Response, NextFunction } from 'express'; import fs from 'fs'; import { InternalServerError } from '../utils/response_handlers/error_categories'; const uploadDir = 'uploads'; if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } export function uploadFileMiddleware(req: Request, res: Response, next: NextFunction) { console.log('Media SERVICE: /upload route hit'); const form = new multiparty.Form({ uploadDir, }); form.parse(req, (err, fields, files) => { if (err) { console.error('Error parsing form:', err); return next(new InternalServerError()); } console.log('FIELDS:', fields); console.log('FILES:', files); const uploadedFile = files.file?.[0]; if (!uploadedFile) { return next(new InternalServerError('No file uploaded')); } console.log('FILE RECEIVED:'); console.log('Original Name:', uploadedFile.originalFilename); console.log('MIME Type:', uploadedFile.headers['content-type']); console.log('File Size:', uploadedFile.size); console.log('Stored at:', uploadedFile.path); // 先初始化req.body为对象,避免undefined赋值报错 req.body = req.body || {}; req.body.uploadedFile = uploadedFile; // 调用next推进请求到后续路由 next(); }); }
2. 确保上传路由不受默认body解析中间件干扰
如果你的Express应用全局使用了express.json()或express.urlencoded(),需要确保上传路由跳过这些中间件——它们会消耗请求流,导致multiparty无法解析文件:
// 应用入口示例 import express from 'express'; import mediaRouter from './routes/media'; const app = express(); // 全局使用body解析中间件,但排除上传路由 app.use(/^(?!\/media\/upload).*$/, express.json()); app.use(/^(?!\/media\/upload).*$/, express.urlencoded({ extended: true })); // 挂载媒体路由 app.use('/media', mediaRouter);
3. 可选:添加全局错误捕获逻辑
在回调内添加try-catch,避免其他未预见的错误导致next()无法执行:
form.parse(req, (err, fields, files) => { try { if (err) { console.error('Error parsing form:', err); return next(new InternalServerError()); } console.log('FIELDS:', fields); console.log('FILES:', files); const uploadedFile = files.file?.[0]; if (!uploadedFile) { return next(new InternalServerError('No file uploaded')); } console.log('FILE RECEIVED:'); console.log('Original Name:', uploadedFile.originalFilename); console.log('MIME Type:', uploadedFile.headers['content-type']); console.log('File Size:', uploadedFile.size); console.log('Stored at:', uploadedFile.path); req.body = req.body || {}; req.body.uploadedFile = uploadedFile; next(); } catch (error) { console.error('Middleware error:', error); next(new InternalServerError('File upload middleware failed')); } });
内容的提问来源于stack exchange,提问作者Deepak Singh
相关产品推荐
相关产品推荐

