Next.js 15 App Router报错:TypeError: req.on is not a function
解决Next.js 15 App Router中formidable报错
req.on is not a function的问题 问题根源
Next.js 15 App Router的API路由里,POST方法接收的req是Web标准的Request对象,而非Node.js传统的http.IncomingMessage。而formidable的form.parse()方法默认只兼容Node.js的请求对象(依赖其on事件监听方法),直接传入App Router的req就会触发TypeError: req.on is not a function。
修复方案
方案一:使用formidable的Promise式解析(推荐)
formidable支持直接解析Web Request对象,用Promise替代回调写法更适配App Router:
import { IncomingForm } from "formidable"; import { promises as fs } from 'fs'; import path from 'path'; const UPLOAD_DIR = path.join(process.cwd(), 'tmp/uploads'); // 确保临时上传目录存在 await fs.mkdir(UPLOAD_DIR, { recursive: true }); export async function POST(req: Request) { const form = new IncomingForm({ uploadDir: UPLOAD_DIR, keepExtensions: true, maxFileSize: 10 * 1024 * 1024, // 10MB限制 }); try { // 直接解析Web Request对象 const { fields, files } = await form.parse(req); // 这里添加你的视频处理逻辑 // ... return new Response(JSON.stringify({ success: true, files }), { status: 200 }); } catch (err) { console.error('表单解析失败:', err); return new Response(JSON.stringify({ error: '表单解析错误' }), { status: 500 }); } }
方案二:将Web Request转换为Node.js可读流
如果需要兼容旧版formidable或回调写法,可以手动把Web Request转为Node.js兼容的流:
import { IncomingForm } from "formidable"; import { Readable } from 'stream'; import path from 'path'; const UPLOAD_DIR = path.join(process.cwd(), 'tmp/uploads'); // 声明使用Node.js运行时(如果需要Node特定API) export const runtime = 'nodejs'; export async function POST(req: Request) { const form = new IncomingForm({ uploadDir: UPLOAD_DIR, keepExtensions: true, maxFileSize: 10 * 1024 * 1024, }); // 将Web Request的body转为Node.js可读流 const nodeReq = Readable.from(await req.arrayBuffer()); // 补充formidable需要的请求属性 (nodeReq as any).headers = req.headers; (nodeReq as any).method = req.method; (nodeReq as any).url = req.url; return new Promise((resolve, reject) => { form.parse(nodeReq, async (err, fields, files) => { if (err) { console.error('表单解析错误:', err); return resolve(new Response(JSON.stringify({ error: '表单解析失败' }), { status: 500 })); } // 处理视频逻辑 // ... resolve(new Response(JSON.stringify({ success: true }), { status: 200 })); }); }); }
额外注意事项
- 务必确保
UPLOAD_DIR目录存在,建议在代码中添加自动创建逻辑(如方案一中的fs.mkdir) - 如果使用Node.js专属API(如
fs同步方法),需要在路由文件顶部添加export const runtime = 'nodejs';,指定使用Node.js运行时 - 临时上传的文件处理完成后,记得清理
UPLOAD_DIR,避免磁盘空间浪费
内容的提问来源于stack exchange,提问作者rafbanaan
相关产品推荐
相关产品推荐

