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

React上传图片至Strapi遇500错误,请求修复方案

修复Strapi表单提交图片时的500错误

问题根源

  1. Strapi的文件上传需单独调用/upload接口,不能直接将文件数据和普通表单字段一起提交到实体接口(如/links),否则会触发500错误。
  2. 原代码中处理file类型输入的逻辑错误,无法正确获取文件对象,导致上传数据格式不合法。
  3. 复选框的状态处理逻辑错误,无法正确获取选中状态。

修复方案

1. 修正输入处理逻辑

针对文件输入和复选框单独处理,确保能正确获取对应值:

const handleChange = (e) => {
  const name = e.target.name;
  let value = e.target.value;
  // 处理文件输入,获取真实文件对象
  if (e.target.type === "file") {
    value = e.target.files[0];
  }
  // 处理复选框,获取选中状态
  if (e.target.type === "checkbox") {
    value = e.target.checked;
  }
  setInputs((values) => ({ ...values, [name]: value }));
};

2. 调整提交流程:先传文件再创建实体

先通过/upload接口上传图片,拿到文件ID后,再将ID与其他表单数据一起提交到/links接口完成关联:

const handleSubmit = async (e) => {
  e.preventDefault();
  
  let featuredImageId = null;
  // 上传图片(如果用户选择了图片)
  if (inputs.featuredimg) {
    const formData = new FormData();
    formData.append("files", inputs.featuredimg);
    // 关联到Link模型的featuredimg字段(需和Strapi模型配置一致)
    formData.append("ref", "api::link.link");
    formData.append("field", "featuredimg");

    try {
      const uploadRes = await axios.post(
        `${backendUrl}/api/upload`,
        formData,
        { 
          headers: { 
            Authorization: `Bearer ${token}`, 
            "Content-Type": "multipart/form-data" 
          } 
        }
      );
      featuredImageId = uploadRes.data[0].id;
    } catch (uploadError) {
      console.error("图片上传失败:", uploadError);
      return;
    }
  }

  // 提交Link数据
  try {
    const linkRes = await axios.post(
      `${backendUrl}/api/links`,
      {
        data: {
          userid: user.id,
          slug: inputs.name.replace(/\W+/g, "-") + "-" + randomNumberForSlug,
          url: inputs.url,
          name: inputs.name,
          body: inputs.body,
          type: inputs.type,
          nsfw: inputs.nsfw || false,
          public: inputs.public !== undefined ? inputs.public : true,
          featuredimg: featuredImageId,
        },
      },
      { headers: { Authorization: `Bearer ${token}` } }
    );
    console.log("链接创建成功:", linkRes);
  } catch (linkError) {
    console.error("链接创建失败:", linkError);
  }
};

3. 修正文件输入组件的属性

文件输入无法通过value绑定状态,直接移除该属性:

<Input
  type="file"
  name="featuredimg"
  placeholder="Featured Image"
  onChange={handleChange}
/>

完整修改后的代码

import React, { useState } from "react";
import {
  Button,
  FormControl,
  FormLabel,
  Input,
  Checkbox,
  VStack,
  Select,
  Heading,
  Textarea,
} from "@chakra-ui/react";
import { useSelector } from "react-redux";
import axios from "axios";

const backendUrl = process.env.REACT_APP_API_URL;

export default function AddLinkView() {
  const { user } = useSelector((state) => state.user);
  const token = localStorage.getItem("jwt");
  const [inputs, setInputs] = useState({});

  const handleChange = (e) => {
    const name = e.target.name;
    let value = e.target.value;
    if (e.target.type === "file") {
      value = e.target.files[0];
    }
    if (e.target.type === "checkbox") {
      value = e.target.checked;
    }
    setInputs((values) => ({ ...values, [name]: value }));
  };

  const randomNumberForSlug = Math.floor(Math.random() * 10000);

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    let featuredImageId = null;
    if (inputs.featuredimg) {
      const formData = new FormData();
      formData.append("files", inputs.featuredimg);
      formData.append("ref", "api::link.link");
      formData.append("field", "featuredimg");

      try {
        const uploadRes = await axios.post(
          `${backendUrl}/api/upload`,
          formData,
          { 
            headers: { 
              Authorization: `Bearer ${token}`, 
              "Content-Type": "multipart/form-data" 
            } 
          }
        );
        featuredImageId = uploadRes.data[0].id;
      } catch (uploadError) {
        console.error("图片上传失败:", uploadError);
        return;
      }
    }

    try {
      const linkRes = await axios.post(
        `${backendUrl}/api/links`,
        {
          data: {
            userid: user.id,
            slug: inputs.name.replace(/\W+/g, "-") + "-" + randomNumberForSlug,
            url: inputs.url,
            name: inputs.name,
            body: inputs.body,
            type: inputs.type,
            nsfw: inputs.nsfw || false,
            public: inputs.public !== undefined ? inputs.public : true,
            featuredimg: featuredImageId,
          },
        },
        { headers: { Authorization: `Bearer ${token}` } }
      );
      console.log("链接创建成功:", linkRes);
    } catch (linkError) {
      console.error("链接创建失败:", linkError);
    }
  };

  return (
    <>
      <form onSubmit={handleSubmit}>
        <FormControl bg="white" p={6} rounded="xl" >
          <Heading as="h1" size="xl" pb={6}>
            Ajouter un article
          </Heading>
          <VStack spacing={2} align="stretch" w="75%">
            <FormLabel>URL</FormLabel>
            <Input
              bg="white"
              type="text"
              name="url"
              placeholder="Add your URL"
              value={inputs.url || ""}
              onChange={handleChange}
            />
            <FormLabel>Titre</FormLabel>
            <Input
              bg="white"
              type="text"
              name="name"
              placeholder="Name"
              value={inputs.name || ""}
              onChange={handleChange}
            />
            <FormLabel>Image</FormLabel>
            <Input
              type="file"
              name="featuredimg"
              placeholder="Featured Image"
              onChange={handleChange}
            />

            <FormLabel>Description </FormLabel>
            <Textarea
              bg="white"
              name="body"
              placeholder="Add your description"
              value={inputs.body || ""}
              onChange={handleChange}
            />
            <FormLabel>Type</FormLabel>
            <Select
              placeholder="Select option"
              name="type"
              value={inputs.type || ""}
              onChange={handleChange}
            >
              <option value="lien">lien</option>
              <option value="image">image</option>
              <option value="video">video</option>
            </Select>
            <FormLabel>Votre lien est pour un public adulte ?</FormLabel>
            <Checkbox
              colorScheme="red"
              bg="white"
              name="nsfw"
              isChecked={inputs.nsfw || false}
              onChange={handleChange}
            >
              Adult only
            </Checkbox>
            <FormLabel>Rendre ce lien privé</FormLabel>
            <Checkbox
              colorScheme="red"
              bg="white"
              name="public"
              isChecked={inputs.public !== undefined ? inputs.public : true}
              onChange={handleChange}
            >
              Private link
            </Checkbox>

            <Button
              colorScheme="green"
              type="submit"
              w={{ base: "100%", md: "max-content" }}
            >
              Submit
            </Button>
          </VStack>
        </FormControl>
      </form>
    </>
  );
}

额外注意事项

  • 确保Strapi的Link模型中已创建featuredimg字段,类型设置为Media(单文件)。
  • 检查Strapi权限配置,确保upload和links接口的创建权限对已认证用户开放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:16:04