调用DALL·E图像变体API报错:'image'为必填属性求排查
问题排查:DALL·E图像变体API返回"'image'是必填属性"错误
我尝试调用DALL·E Create图像变体API,但每次POST请求都返回如下错误:
error: { "code": null, "message": "'image' is a required property", "param": null, "type": "invalid_request_error" }
使用Next.js开发,相关代码如下:
const [selectedImage, setSelectedImage] = useState<File | null>(null); const endpoint = "https://api.openai.com/v1/images/variations"; async function onSubmit(event: React.FormEvent<HTMLFormElement>) { event.preventDefault(); if (!selectedImage) { toast(t("alert"), { icon: "❌", }); return; } const imageSize = selectedValue === "Small" ? "256x256" : selectedValue === "Medium" ? "512x512" : "1024x1024"; setLoading(true); const headers = { "Content-Type": "multipart/form-data", Authorization: `Bearer ${process.env.NEXT_PUBLIC_OPENAI_API_KEY}`, }; const formData = new FormData(); formData.append("image", selectedImage); formData.append("n", String(number)); formData.append("size", imageSize); formData.append("response_format", "url"); try { const response = await fetch(endpoint, { method: "POST", body: formData, headers: headers, }); const data = await response.json(); console.log(data); } catch (error) { console.error(error); throw error; } finally { setLoading(false); } }
图片选择逻辑代码:
const handleImageSelect = (event: React.ChangeEvent<HTMLInputElement>) => { const file = event.target.files && event.target.files[0]; if (file) { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => { setSelectedImage(file); }; } };
问题原因及解决方案
1. 手动设置Content-Type导致FormData解析失败
当使用fetch发送FormData时,不需要手动设置Content-Type: multipart/form-data。浏览器会自动生成包含正确boundary分隔符的Content-Type头,手动设置会丢失boundary信息,导致OpenAI API无法正确解析FormData中的image字段。
修改headers部分,移除多余的Content-Type:
const headers = { Authorization: `Bearer ${process.env.NEXT_PUBLIC_OPENAI_API_KEY}`, };
2. 验证输入图片是否符合API要求
DALL·E图像变体API对输入图片有严格要求:
- 必须是PNG格式
- 尺寸为正方形(256x256、512x512或1024x1024)
- 文件大小不超过4MB
可以在图片选择时提前验证,避免无效请求:
const handleImageSelect = (event: React.ChangeEvent<HTMLInputElement>) => { const file = event.target.files && event.target.files[0]; if (file) { // 验证图片格式 if (!file.type.includes('image/png')) { toast('请选择PNG格式的图片', { icon: "❌" }); return; } // 验证图片尺寸是否为正方形 const img = new Image(); img.onload = () => { if (img.width !== img.height) { toast('请选择正方形的图片', { icon: "❌" }); return; } setSelectedImage(file); }; img.onerror = () => { toast('图片加载失败,请重新选择', { icon: "❌" }); }; img.src = URL.createObjectURL(file); // 若不需要预览图片,可直接移除FileReader逻辑 } };
3. 修复API密钥暴露的安全问题
当前代码使用NEXT_PUBLIC_OPENAI_API_KEY会将密钥暴露在前端代码中,极易被恶意盗用。正确做法是通过Next.js的API路由封装请求,由后端调用OpenAI API:
创建API路由(pages/api/variations.ts)
import type { NextApiRequest, NextApiResponse } from 'next'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method !== 'POST') { return res.status(405).json({ error: '仅支持POST请求' }); } const formData = new FormData(); // 从请求体中获取FormData字段 formData.append('image', req.body.image); formData.append('n', req.body.n); formData.append('size', req.body.size); formData.append('response_format', 'url'); try { const response = await fetch('https://api.openai.com/v1/images/variations', { method: 'POST', body: formData, headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}`, }, }); const data = await response.json(); res.status(response.status).json(data); } catch (error) { res.status(500).json({ error: '生成图像变体失败' }); } }
前端修改请求地址
// 替换原endpoint为自己的API路由 const response = await fetch('/api/variations', { method: "POST", body: formData, });
内容的提问来源于stack exchange,提问作者Umer Arif
相关产品推荐
相关产品推荐

