You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 17:52:21