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

如何使用next-safe-action & react-hook-form向Server Action发送文件数据

解决next-safe-action提交File类型数据到Server Action的报错问题

错误Only plain objects, and a few built-ins, can be passed to Server Actions. Classes or null prototypes are not supported的核心原因是:你直接传递了包含File类实例的对象给Server Action,而Next.js禁止传递类实例,仅允许纯对象或特定内置类型。FormData是支持File传递的合法类型,next-safe-action完全兼容这种处理方式,以下是具体解决步骤:

解决方法:将表单数据转为FormData传递

1. 修改前端onSubmit函数,生成FormData

把form.getValues()返回的对象转换为FormData,确保File实例被正确包含:

async function onSubmit() {
  const formValues = form.getValues();
  const formData = new FormData();

  // 遍历表单字段,添加到FormData
  Object.entries(formValues).forEach(([key, value]) => {
    if (Array.isArray(value)) {
      // 处理多文件/数组类型字段
      value.forEach(item => {
        formData.append(key, item instanceof File ? item : JSON.stringify(item));
      });
    } else if (value instanceof File) {
      formData.append(key, value);
    } else {
      // 非File类型转为JSON字符串,方便后端解析复杂结构
      formData.append(key, JSON.stringify(value));
    }
  });

  if (product) {
    await executeUpdate(formData);
  } else {
    await executeCreate(formData);
  }

  router.refresh();
  form.reset(form.getValues());
}

2. 调整Server Action(createProductAction)处理FormData

使用next-safe-action的parseFormData工具结合Zod Schema解析FormData,保证类型安全:

import { z } from 'zod';
import { createSafeActionClient, parseFormData } from 'next-safe-action';

const actionClient = createSafeActionClient();

// 定义产品创建的校验Schema
const CreateProductSchema = z.object({
  name: z.string(),
  price: z.coerce.number(),
  image: z.instanceof(File), // 声明File类型字段
  // 其他业务字段按需添加
});

export const createProductAction = actionClient
  .action(async ({ rawInput }) => {
    // 解析FormData到Schema定义的结构
    const parsedInput = await parseFormData(CreateProductSchema, rawInput as FormData);

    // 执行业务逻辑:比如上传文件到存储、写入数据库等
    // 示例:const uploadedUrl = await uploadToStorage(parsedInput.image);

    return {
      data: { message: '产品创建成功' },
    };
  });

补充说明

  • 若使用react-hook-form,也可直接通过form.handleSubmit自动生成FormData,手动转换则更适配复杂字段场景。
  • 非File类型字段转为JSON字符串是为了兼容对象、数组等复杂结构,后端解析时用JSON.parse()还原即可。

内容的提问来源于stack exchange,提问作者Amin Afshari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 02:22:44