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
相关产品推荐
相关产品推荐

