NextJS 13基于formidable的文件上传API报错:TypeError: req.on is not a function
解决Next.js 13 App Router中Formidable文件上传API的
req.on is not a function错误 问题原因
Next.js 13 App Router的路由处理函数接收的req是NextRequest对象(基于Web Streams API),而非传统Pages Router中的Node.js原生IncomingMessage。Formidable默认依赖Node.js的事件流(req.on),直接传入NextRequest会导致方法不存在的错误。
解决方案
方法1:使用Formidable v3+的Web Streams支持
Formidable v3及以上版本支持直接处理Web Streams,无需转换为Node.js原生请求对象,步骤如下:
- 安装最新版Formidable:
npm install formidable@latest
- 修改
app/api/uploadfile/route.ts代码:
import { IncomingForm } from "formidable"; import { type NextRequest } from "next/server"; export async function POST(req: NextRequest) { const form = new IncomingForm({ multiples: true }); // 从NextRequest获取表单数据并解析 const formData = await req.formData(); const { fields, files } = await form.parse(formData); // 示例:打印上传内容 console.log("上传字段:", fields); console.log("上传文件:", files); // 返回CKEditor5要求的响应格式 return new Response(JSON.stringify({ uploaded: true, url: "/uploads/" + (files.image as any)[0].name // 替换为实际文件访问路径 }), { status: 200 }); }
方法2:兼容旧版Formidable(转换为Node.js原生请求)
如果需要使用Formidable v2或更低版本,需将NextRequest转换为Node.js原生请求对象:
import { IncomingForm } from "formidable"; import { type NextRequest } from "next/server"; import { Readable } from "stream"; export async function POST(req: NextRequest) { // 将NextRequest的Web Stream转换为Node.js Readable流 const readable = Readable.from(req.body as AsyncIterable<Uint8Array>); // 模拟Node.js原生请求的必要方法 const nodeReq = { ...req, readable, on: readable.on.bind(readable), pipe: readable.pipe.bind(readable), } as any; const form = new IncomingForm({ multiples: true }); const { fields, files } = await new Promise((resolve, reject) => { form.parse(nodeReq, (err, fields, files) => { if (err) reject(err); else resolve({ fields, files }); }); }); // 返回CKEditor5适配的响应 return new Response(JSON.stringify({ uploaded: true, url: "/uploads/" + (files.image as any)[0].name // 替换为实际存储后的访问URL }), { status: 200 }); }
关键注意事项
- 请求方法:CKEditor5上传适配器默认使用
POST方法,建议将API方法改为POST,避免额外配置。 - 响应格式:CKEditor5要求响应必须包含
uploaded(布尔值)和url(文件访问地址字符串)两个字段,否则会判定上传失败。 - 文件存储:示例仅做解析演示,实际需将文件保存到本地或云存储服务,并返回对应的可访问URL。
- TypeScript类型优化:避免使用
any,可导入Formidable类型定义:import type { Fields, Files } from "formidable";
内容的提问来源于stack exchange,提问作者DarkArcane
相关产品推荐
相关产品推荐

