Next.js中React Hook Form发送FormData失败及路由处理器报错排查
在Next.js中使用React Hook Form发送FormData上传文件的问题解决
你遇到的核心问题是React Hook Form默认无法正确获取file输入的File对象,导致后端拿到的不是合法的File类型,调用arrayBuffer()时报错。另外FormData.append()本身没有返回值,所以console.log(port)显示undefined是正常现象,无需关注。
解决方案步骤:
1. 修正File输入的React Hook Form绑定逻辑
React Hook Form对file input的默认处理只会返回文件名字符串,而非File对象。需要自定义onChange事件手动获取并更新表单值:
<FormField control={form.control} name="media" render={({ field: { onChange, name } }) => ( <FormItem> <FormControl> <Input type="file" placeholder="media" onChange={(e) => { // 获取选中的第一个文件 const file = e.target.files?.[0]; if (file) { // 手动将File对象更新到表单 onChange(file); } }} name={name} /> </FormControl> <FormMessage /> </FormItem> )} />
2. 修正表单类型定义
确保Inputs类型中media的类型为File | null,避免类型不匹配:
type Inputs = { media: File | null; description: string; // 其他表单字段... };
3. 优化FormData组装逻辑
FormData.append()无返回值,无需赋值给变量;同时要判断文件是否存在再追加:
const onSubmit = async (data: Inputs) => { console.log("data", data); const formData = new FormData(); // 仅当文件存在时追加到FormData if (data.media) { formData.append("media", data.media); } formData.append("description", data.description); try { setSubmitted(true); if (porfolio) { await fetch(`/api/portfolio/${porfolio.id}`, { method: "PATCH", body: formData, }); setOpen(false); toast.success("更新成功。"); } else { const port = await fetch("/api/portfolio", { method: "POST", body: formData, }); console.log("port", port); setOpen(false); toast.success("作品集已创建,前往/portfolio查看变更。"); form.reset(); await port.json(); } router.refresh(); } catch (error) { setSubmitted(false); setError("处理过程中发生错误,请联系开发者。"); } };
4. 后端增加安全校验
在路由处理器中先校验拿到的是否为合法File对象,避免报错:
export async function POST(request: NextRequest) { const body = await request.formData(); const file = body.get("media"); // 校验是否为有效File对象 if (!(file instanceof File)) { return new Response("未上传有效文件", { status: 400 }); } console.log("file:", file); const arrayBuffer = await file.arrayBuffer(); const buffer = new Uint8Array(arrayBuffer); // 后续业务逻辑... }
内容的提问来源于stack exchange,提问作者Akinola
相关产品推荐
相关产品推荐

