React Native应用获取OpenAI生成图片Blob遇跨域问题求助
解决OpenAI图片URL跨域上传至Supabase Storage的问题
问题原因
OpenAI生成的图片URL设置了严格的CORS规则,不允许前端(如localhost:19006这类本地域名)直接通过fetch请求获取Blob资源,从而触发跨域报错。
解决方案
方案一:使用Supabase Edge Functions中转请求
通过Supabase边缘函数在服务端请求OpenAI图片URL,再将文件上传至Storage,避开前端的CORS限制。
- 创建Supabase Edge Function
// supabase/functions/upload-openai-image/index.ts import { createClient } from '@supabase/supabase-js'; import { serve } from 'https://deno.land/std@0.192.0/http/server.ts'; serve(async (req) => { const { imageUrl, fileName } = await req.json(); const supabase = createClient( Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')! ); // 服务端请求图片,不受CORS限制 const imageResponse = await fetch(imageUrl); const blob = await imageResponse.blob(); // 上传至Supabase Storage const { data, error } = await supabase.storage .from('public/posts') .upload(fileName, blob); if (error) { return new Response(JSON.stringify({ error: error.message }), { status: 500 }); } return new Response(JSON.stringify({ data }), { status: 200 }); });
- 部署Edge Function
supabase functions deploy upload-openai-image
- 前端调用该函数
const fileName = `${Date.now()}-${Math.floor(Math.random() * 100000)}.png`; // 调用Edge Function中转上传 const response = await fetch('https://<你的Supabase项目ID>.functions.supabase.co/upload-openai-image', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${supabase.auth.session()?.access_token}` }, body: JSON.stringify({ imageUrl: url, fileName }) }); const result = await response.json(); if (result.error) { throw new Error(`上传失败: ${result.error}`); }
方案二:请求OpenAI时直接返回Base64格式
修改OpenAI API调用参数,让其返回图片的Base64数据而非临时URL,直接用Base64转换为Blob后上传至Supabase,无需额外请求图片资源。
- 修改OpenAI API请求
// 调用OpenAI生成图片时指定返回格式为base64 const openAiResponse = await fetch('https://api.openai.com/v1/images/generations', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${你的OpenAI密钥}` }, body: JSON.stringify({ prompt: '你的图片生成提示词', n: 1, size: '1024x1024', response_format: 'b64_json' // 关键:返回Base64数据 }) }); const data = await openAiResponse.json(); const base64Image = data.data[0].b64_json;
- 将Base64转换为Blob并上传
const fileName = `${Date.now()}-${Math.floor(Math.random() * 100000)}.png`; // 将Base64转为Blob const blob = await fetch(`data:image/png;base64,${base64Image}`).then(res => res.blob()); const { data, error } = await supabase.storage .from('public/posts') .upload(fileName, blob); if (error) { throw new Error(`上传失败: ${error.message}`); }
注意事项
- 方案一中,需在Supabase控制台的Edge Functions页面配置环境变量
SUPABASE_URL和SUPABASE_SERVICE_ROLE_KEY。 - 方案二更简洁,无需额外部署服务,适合绝大多数场景。
内容的提问来源于stack exchange,提问作者Globe
相关产品推荐
相关产品推荐

