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

如何用Fetch API提交FormData?解决POST请求420错误

修复Fetch API提交表单时的420错误

问题描述

需要提交的表单数据结构:

{
    "code": "test1",
    "article": "door",
    "price": 12,
    "vat": null,
    "status": 1,
    "company_id": 10
}

点击Add按钮通过Fetch API提交时,控制台出现420错误:

POST https://api.factarni.tn/article/create   420

当前实现代码:

const New = ({ inputs, title }) => {
  const handleClick = (e) => {
    e.preventDefault();

    fetch("https://api.factarni.tn/article/create", {
      method: "POST",
      body: JSON.stringify({
        code: "test1",
        article: "door",
        price: 12,
        vat: null,
        status: 1,
        company_id: 30,
      }),
      headers: {
        Authorization:
          "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImFkMWIxOWYwZjU4ZTJjOWE5Njc3M2M5MmNmODA0NDEwMTc5NzEzMjMiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoibW9oYW1lZCIsImlzcyI6Imh0dHBzOi8vc2VjdXJldG9rZW4uZ29vZ2xlLmNvbS9mYWN0YXJuaSIsImF1ZCI6ImZhY3Rhcm5pIiwiYXV0aF90aW1lIjoxNjYwNzIzNDA5LCJ1c2VyX2lkIjoiQ3hKejMwR1ExYlVLMVd0SjdDa1NVUzJ4NW5rMSIsInN1YiI6IkN4SnozMEdRMWJVSzFXdEo3Q2tTVVMyeDVuazEiLCJpYXQiOjE2NjA3MjM0MDksImV4cCI6MTY2MDcyNzAwOSwiZW1haWwiOiJpZHJpc3Ntb3VoYW1lZDg0MUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJpZHJpc3Ntb3VoYW1lZDg0MUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ.XoDs7DEYWQm9AwWFEbR7CtKpgvTh_zH8E5V1e8nUp5OwQT3hjKMUBFRCa7p_v-1TXAF5VoSDGTt0vZRgtPj6u7mIzagi0CPkuQYVyUkhHo2wBOV-IHbCRTqg-M4d6WDQvfSp1C0OzUnEg8eduUr7F7znuLnAUZQKBZ_Xp9ogj8aAZo-R8Na0HE5h0L9fIslD9UFBj2192EVebpb2DJir16beotXpd04d_qC1WCrN3WMsWdvgl2BRrTiG6SkqqwZH1hZzNkajNtIrhpYLnSOBoE3SsiIczvctqexynxmlle7gWaBN22t1M3sk3NHCkdfkSrXRi3PIBr71qw2QWltkyA",
      },
    }).then((response) => response.json());
  };

  return (
    <div className="New">
      <Sidebar />
      <div className="newContainer">
        <Navbar />
        <div className="top">
          <h1>{title}</h1>
        </div>
        <div className="bottom">
          <div className="right">
            <form>
              <div className="formInput"></div>
              {inputs.map((input) => (
                <div className="formInput" key={input.id}>
                  <label>{input.label} </label>
                  <input type={input.type} placeholder={input.placeholder} />
                </div>
              ))}
              <button onClick={handleClick}>Add</button>
            </form>
          </div>
        </div>
      </div>
    </div>
  );
};

export default New;

修复方案

420属于自定义HTTP状态码,通常和请求格式、令牌有效性、限流规则相关,按以下步骤排查修复:

1. 补充Content-Type请求头

API无法识别JSON格式的请求体,需添加Content-Type: application/json头:

headers: {
  Authorization: "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImFkMWIxOWYwZjU4ZTJjOWE5Njc3M2M5MmNmODA0NDEwMTc5NzEzMjMiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoibW9oYW1lZCIsImlzcyI6Imh0dHBzOi8vc2VjdXJldG9rZW4uZ29vZ2xlLmNvbS9mYWN0YXJuaSIsImF1ZCI6ImZhY3Rhcm5pIiwiYXV0aF90aW1lIjoxNjYwNzIzNDA5LCJ1c2VyX2lkIjoiQ3hKejMwR1ExYlVLMVd0SjdDa1NVUzJ4NW5rMSIsInN1YiI6IkN4SnozMEdRMWJVSzFXdEo3Q2tTVVMyeDVuazEiLCJpYXQiOjE2NjA3MjM0MDksImV4cCI6MTY2MDcyNzAwOSwiZW1haWwiOiJpZHJpc3Ntb3VoYW1lZDg0MUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJpZHJpc3Ntb3VoYW1lZDg0MUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ.XoDs7DEYWQm9AwWFEbR7CtKpgvTh_zH8E5V1e8nUp5OwQT3hjKMUBFRCa7p_v-1TXAF5VoSDGTt0vZRgtPj6u7mIzagi0CPkuQYVyUkhHo2wBOV-IHbCRTqg-M4d6WDQvfSp1C0OzUnEg8eduUr7F7znuLnAUZQKBZ_Xp9ogj8aAZo-R8Na0HE5h0L9fIslD9UFBj2192EVebpb2DJir16beotXpd04d_qC1WCrN3WMsWdvgl2BRrTiG6SkqqwZH1hZzNkajNtIrhpYLnSOBoE3SsiIczvctqexynxmlle7gWaBN22t1M3sk3NHCkdfkSrXRi3PIBr71qw2QWltkyA",
  "Content-Type": "application/json"
}

2. 验证JWT令牌与权限

  • 解码JWT令牌,检查exp字段确认是否过期;
  • 核对company_id:你示例表单用的是10,但代码里传的是30,确认该ID是否属于当前用户有权限操作的范围;
  • 若令牌过期,重新获取有效的Authorization令牌。

3. 检查请求限流

420可能是API触发了频率限制,暂停一段时间后重试,或确认API的调用次数限制规则。

4. 同步表单输入与提交数据

当前提交的是硬编码数据,表单输入未被收集,改用状态管理获取真实用户输入:

import { useState } from 'react';

const New = ({ inputs, title }) => {
  const [formData, setFormData] = useState({
    code: "",
    article: "",
    price: "",
    vat: null,
    status: 1,
    company_id: 10
  });

  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: name === 'price' ? Number(value) : value
    }));
  };

  const handleClick = (e) => {
    e.preventDefault();

    fetch("https://api.factarni.tn/article/create", {
      method: "POST",
      body: JSON.stringify(formData),
      headers: {
        Authorization: "Bearer ...",
        "Content-Type": "application/json"
      },
    })
    .then(response => {
      if (!response.ok) throw new Error(`状态码: ${response.status}`);
      return response.json();
    })
    .then(data => console.log('提交成功:', data))
    .catch(err => console.error('提交失败:', err));
  };

  return (
    <div className="New">
      <Sidebar />
      <div className="newContainer">
        <Navbar />
        <div className="top">
          <h1>{title}</h1>
        </div>
        <div className="bottom">
          <div className="right">
            <form>
              {inputs.map((input) => (
                <div className="formInput" key={input.id}>
                  <label>{input.label} </label>
                  <input 
                    type={input.type} 
                    placeholder={input.placeholder}
                    name={input.name} // 确保inputs数组包含对应字段名(如code、article)
                    value={formData[input.name]}
                    onChange={handleInputChange}
                  />
                </div>
              ))}
              <button onClick={handleClick}>Add</button>
            </form>
          </div>
        </div>
      </div>
    </div>
  );
};

export default New;

5. 捕获响应错误

添加错误处理逻辑,打印详细错误信息,帮助定位问题:

fetch(...)
.then(response => {
  if (!response.ok) {
    return response.text().then(text => { throw new Error(`请求失败: ${response.status} - ${text}`); });
  }
  return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('错误详情:', error));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 05:45:35