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

React-Router-Dom Action处理文件POST请求报错:无法读取profilePhoto

React-Router-Dom Action处理文件上传POST请求的问题解决

问题说明

使用React-Router-Dom的<Form>组件提交包含多个文件输入项的表单,在对应的Action函数中处理POST请求时,服务器返回错误:无法读取未定义的属性'profilePhoto'。

原表单代码

<Form method="post"> 
  <div>
    <label htmlFor="tradeLicensePhoto">Copy of trade license</label>
    <input
      id="tradeLicensePhoto"
      type="file"
      name="tradeLicensePhoto"
    />
  </div>
  <div>
    <label htmlFor="profilePhoto">Profile Photo</label>
    <input
      id="profilePhoto"
      type="file"
      name="profilePhoto"
    />
  </div>
  <div>
    <label htmlFor="coverPhoto">Cover Photo</label>
    <input
      id="coverPhoto"
      type="file"
      name="coverPhoto"
    />
  </div>
  <div>
    <label htmlFor="frontIdPhoto">Front ID Photo</label>
    <input
      id="frontIdPhoto"
      type="file"
      name="frontIdPhoto"
    />
  </div>
  <div>
    <label htmlFor="backIdPhoto">Back ID Photo</label>
    <input
      id="backIdPhoto"
      type="file"
      name="backIdPhoto"
    />
  </div>
  <button>{isSubmitting ? "Submitting..." : "Save"}</button>
</Form>

原Action函数代码

export async function authenticationAction({ request }) {
  const data = await request.formData();
  const authData = {
    tradeLicensePhoto: data.get("tradeLicensePhoto"),
    profilePhoto: data.get("profilePhoto"),
    coverPhoto: data.get("coverPhoto"),
    frontIdPhoto: data.get("frontIdPhoto"),
    backIdPhoto: data.get("backIdPhoto"),
  };
  const response = await fetch(
    `API-LINK`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(authData),
    }
  );
  if (!response.ok) {
    throw json({ message: "Could not authenticate user." }, { status: 500 });
  }
}

错误原因

  1. 表单编码类型不匹配:默认<Form>组件的enctype为application/x-www-form-urlencoded,无法正确传输文件,必须使用multipart/form-data格式。
  2. 文件对象无法JSON序列化:File对象不能通过JSON.stringify()处理,序列化后文件字段会变成空对象或undefined,导致服务器接收到的数据中profilePhoto等字段不存在。
  3. 请求头与数据格式矛盾:手动设置Content-Type: application/json,但实际发送的是无法被正确解析的序列化对象,服务器无法识别文件数据。

修复步骤

  1. 为表单添加正确的编码类型:在<Form>标签中加入enctype="multipart/form-data",确保表单以文件传输的标准格式提交。
  2. 直接发送FormData:Action函数中无需将FormData转为JSON,直接把获取到的data作为fetch的body发送,同时移除手动设置的Content-Type头,让浏览器自动添加正确的multipart/form-data头及边界标识。

修改后的代码

表单组件

<Form method="post" enctype="multipart/form-data">
  <div>
    <label htmlFor="tradeLicensePhoto">Copy of trade license</label>
    <input
      id="tradeLicensePhoto"
      type="file"
      name="tradeLicensePhoto"
    />
  </div>
  <div>
    <label htmlFor="profilePhoto">Profile Photo</label>
    <input
      id="profilePhoto"
      type="file"
      name="profilePhoto"
    />
  </div>
  <div>
    <label htmlFor="coverPhoto">Cover Photo</label>
    <input
      id="coverPhoto"
      type="file"
      name="coverPhoto"
    />
  </div>
  <div>
    <label htmlFor="frontIdPhoto">Front ID Photo</label>
    <input
      id="frontIdPhoto"
      type="file"
      name="frontIdPhoto"
    />
  </div>
  <div>
    <label htmlFor="backIdPhoto">Back ID Photo</label>
    <input
      id="backIdPhoto"
      type="file"
      name="backIdPhoto"
    />
  </div>
  <button>{isSubmitting ? "Submitting..." : "Save"}</button>
</Form>

Action函数

export async function authenticationAction({ request }) {
  const data = await request.formData();
  const response = await fetch(
    `API-LINK`,
    {
      method: "POST",
      body: data,
    }
  );
  if (!response.ok) {
    throw json({ message: "无法完成用户认证。" }, { status: 500 });
  }
}

额外注意事项

  • 服务器端需配置支持解析multipart/form-data的中间件(比如Express框架的multer),才能正确接收并处理上传的文件。
  • 若需添加非文件字段,可通过data.append(key, value)直接将字段加入FormData中。

内容的提问来源于stack exchange,提问作者Ali Hsaino

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 15:29:52