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
相关产品推荐
相关产品推荐

