
本文详解在 Next.js 13 App Router 中通过 POST 路由处理器(Route Handler)接收 application/x-www-form-urlencoded 表单数据的方法,重点说明为何不能直接读取 req.body,以及如何使用 req.formData() 安全、可靠地提取字段。
本文详解在 next.js 13 app router 中通过 `post` 路由处理器(route handler)接收 `application/x-www-form-urlencoded` 表单数据的方法,重点说明为何不能直接读取 `req.body`,以及如何使用 `req.formdata()` 安全、可靠地提取字段。
在 Next.js 13 的 App Router 架构下,服务端表单提交需通过 Route Handler(即 app/submit/route.ts)处理,而非传统中间件(Middleware)或 API 路由(Pages Router 风格)。关键点在于:URL 编码的表单数据(application/x-www-form-urlencoded)不能通过 req.body 直接访问——因为 req.body 是一个 ReadableStream,需手动解析,而 Next.js 并未为该 MIME 类型自动解析为对象。
正确做法是调用 req.formData() 方法。该方法专为处理 multipart/form-data 和 application/x-www-form-urlencoded 两类表单请求设计,会自动解析字段并返回 FormData 实例(与浏览器 FormData API 兼容),支持 .get()、.getAll()、.has() 等标准操作。
✅ 正确实现示例(app/submit/route.ts):
import { NextRequest, NextResponse } from 'next/server';
export async function POST(req: NextRequest) {
try {
// ✅ 自动解析 URL-encoded 或 multipart 表单数据
const formData = await req.formData();
const username = formData.get('username')?.toString().trim();
const password = formData.get('password')?.toString().trim();
// 基础校验
if (!username || !password) {
return NextResponse.json(
{ error: 'Username and password are required' },
{ status: 400 }
);
}
// ✅ 此处可接入数据库、验证逻辑、JWT 生成等
console.log('Received login attempt:', { username });
return NextResponse.json(
{ success: true, message: 'Login processed' },
{ status: 200 }
);
} catch (error) {
console.error('Form processing error:', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}⚠️ 注意事项:
- 不要尝试 JSON.parse(await req.text()) 或 await req.json():这仅适用于 application/json 请求,对表单数据会抛出解析错误;
- req.formData() 是异步方法,必须 await:它内部会消费流(stream),重复调用将返回空结果;
- 字段值始终为 string | Blob | null:务必使用可选链(?.toString())并做空值检查,避免运行时错误;
- 安全性提醒:生产环境切勿明文记录或返回密码;应立即进行哈希比对(如使用 bcrypt),且建议添加速率限制与 CSRF 防护(Next.js 13.4+ 支持 csrfToken 集成);
- 前端无需额外配置:你提供的 HTML 表单默认即以 application/x-www-form-urlencoded 提交,完全兼容上述 Route Handler。
总结:Next.js 13 中处理传统表单的核心是 req.formData() —— 它是官方推荐、类型安全、开箱即用的解决方案。放弃对 req.body 的误用,拥抱标准化的表单解析流程,即可稳健支撑登录、注册、搜索等常见业务场景。










