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

ReactJS调用Strapi API时如何将上传图片与内容关联

问题背景

首次在React项目中对接Strapi时,已掌握单独上传图片、单独提交内容的操作方法,但无法将上传的Strapi图片与对应内容条目关联,多次查阅官方文档仍未理清实现逻辑。
当前实现代码如下:

function ProductCreateApi({ evtId }) {
  const [image, setImage] = useState(null)
  const [posts, setPosts] = useState([])
  const [updatesData, setUpdatesData] = useState({
    titleproductgroup: "",
  })

  function updateEdit(e) {

    const newupdate = { ...updatesData }
    newupdate[e.target.id] = e.target.value
    setUpdatesData(newupdate)
    console.log(newupdate)
  }

  const handleSubmit = async (e) => {
    console.log('handleSubmit')
    e.preventDefault()

    const formData = new FormData()
    formData.append('files', image) // the pic
    formData.append('ref', 'api::product-group.product-group') // link with my table
    formData.append('refId', evtId)
    formData.append('field', 'picproductgroup') // the row
    axios.post('http://localhost:1337/api/upload/', formData)

    e.preventDefault()
    const res = axios.post(`http://localhost:1337/api/product-groups/`, {
      "data": {
        titleproductgroup: updatesData.titleproductgroup
      }
    })

    if (res.ok) {
      console.log('res.ok')
      console.log('res', res)
      // imageUploaded()
    }
  }

  const handleFileChange = (e) => {
    console.log('handleFileChange')
    console.log(e.target.files[0]) //this will give us an array and we want the first wone so we add 0
    setImage(e.target.files[0])
  }
  return (
    <div>
      <h1> Upload Event Image</h1>

      <form onSubmit={handleSubmit}>
        <input onChange={(e) => updateEdit(e)} id="titleproductgroup" value={updatesData.titleproductgroup} type="text" placeholder={posts.titleproductgroup} />
        <div>
          <input type='file' onChange={handleFileChange} />
        </div>
        <input type='submit' value='Upload' className='btn' />
      </form>
    </div>
  )
}
export default ProductCreateApi

Strapi侧内容模型配置如下:
配置截图

错误原因
  • 执行顺序错误:上传接口的refId参数要求传入已存在的内容条目ID,当前代码先发起图片上传、后创建产品组条目,传入的evtId是组件入参,并非新创建的产品组条目ID,无法完成关联。
  • 异步请求未做时序控制:所有axios请求都未加await,两个请求并行执行,就算ID参数正确,也会因为条目还未创建完成导致关联失败。
  • 重复调用e.preventDefault()无实际意义。
修正方案

Strapi单媒体字段关联有两种可行实现方式,选择其中一种即可:

方式1:分两步请求(适配现有代码逻辑)

严格按照「先创建内容条目拿ID,再上传图片传关联参数」的顺序执行,修正后的提交逻辑代码如下:

const handleSubmit = async (e) => {
  e.preventDefault()
  try {
    // 第一步:先创建产品组条目,拿到生成的条目ID
    const entryRes = await axios.post(`http://localhost:1337/api/product-groups/`, {
      data: {
        titleproductgroup: updatesData.titleproductgroup
      }
    })
    const newEntryId = entryRes.data.data.id

    // 第二步:条目创建成功后,再上传图片并关联
    if (image) {
      const formData = new FormData()
      formData.append('files', image)
      formData.append('ref', 'api::product-group.product-group')
      formData.append('refId', newEntryId) // 传入刚创建的条目ID
      formData.append('field', 'picproductgroup')
      await axios.post('http://localhost:1337/api/upload/', formData)
    }
    console.log('产品组和图片关联创建成功')
  } catch (err) {
    console.error('创建失败:', err)
  }
}

方式2:创建条目时直接传文件(更简洁)

Strapi支持在创建条目的请求中直接传入媒体文件,不需要单独调用上传接口,只需要把FormData的字段对应好即可:

const handleSubmit = async (e) => {
  e.preventDefault()
  try {
    const formData = new FormData()
    // 传入内容字段
    formData.append('data', JSON.stringify({
      titleproductgroup: updatesData.titleproductgroup
    }))
    // 直接传入媒体字段对应的文件
    if (image) {
      formData.append('files.picproductgroup', image)
    }
    // 只需要发一次请求
    const res = await axios.post('http://localhost:1337/api/product-groups/', formData)
    console.log('创建成功', res)
  } catch (err) {
    console.error('创建失败:', err)
  }
}
注意事项
  • 提前在Strapi后台开放对应接口的权限:角色与权限设置里,要给当前使用的角色开放「产品组创建」「文件上传」的接口权限,否则会返回403错误。
  • 如果是多媒体关联字段,方式2里的字段名保持files.picproductgroup即可,多个文件就多次append同名字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 13:21:21