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

Next.js中使用react-hook-form与Zod处理文件上传并传递给use server函数的报错问题

Next.js中使用react-hook-form与Zod处理文件上传并传递给use server函数的报错问题

我太懂你踩的这个坑了!直接把File对象传给Next.js的use server函数肯定会报错,因为浏览器端的File实例是无法被序列化传递到服务器端的——Server Actions(带use server标记的函数)只接受可序列化的普通对象、字符串、数字这类基础类型,File属于浏览器特有的内置对象,不在允许的范围内。

下面给你一步步解决的方案:

1. 先搞清楚问题根源

你当前的表单验证(Zod的z.instanceof(File))在客户端是没问题的,因为File对象在浏览器里存在;但提交时直接把包含File的表单数据传给Server Action,就会触发序列化失败的错误——服务器端根本认不出这个File对象。

2. 改用FormData传递文件(标准解决方案)

处理文件上传的正确姿势是用FormData包装数据,这是浏览器专门为文件上传设计的格式,而且Next.js的Server Actions原生支持接收FormData。

第一步:修改表单提交逻辑

在你的handleSubmit里,把表单数据转换成FormData,再传给Server Action:

const onSubmit = async (formValues) => {
  // 创建FormData实例
  const formData = new FormData();
  // 把文件添加进去
  formData.append('file', formValues.file);
  // 如果还有其他表单字段,也一起追加进去,比如:
  // formData.append('title', formValues.title);
  
  // 调用你的Server Action函数
  await yourServerUploadFunction(formData);
};

第二步:调整Server Action函数

让你的use server函数接收FormData作为参数,然后从中提取文件并验证:

'use server';

import { z } from 'zod';

// 保持你的Zod验证规则不变
const FileUploadSchema = z.object({
  file: z.instanceof(File),
});

export async function yourServerUploadFunction(formData: FormData) {
  // 从FormData中取出文件
  const file = formData.get('file') as File;
  
  // 用Zod做服务器端二次验证(安全起见)
  const validatedData = FileUploadSchema.parse({ file });
  
  // 接下来就可以处理文件了,比如上传到云存储、读取文件内容等
  // 示例:读取文件的ArrayBuffer
  // const fileBuffer = await validatedData.file.arrayBuffer();
  
  // 后续逻辑...
}

3. 额外注意点

  • 你的原FormField代码不需要修改,那部分的文件处理是正确的,问题只出在提交环节。
  • 如果你的表单有多个字段,记得把所有字段都追加到FormData里,不要遗漏。
  • 服务器端的验证不能少,即使客户端已经验证过,也要在Server Action里再做一次,防止恶意请求。

这样调整后,就能顺利把文件传递给Server Action,不会再触发序列化错误啦!

备注:内容来源于stack exchange,提问作者hantoren

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 13:33:10