如何在React+Supabase项目中展示存储于数据库的图片?
解决Supabase存储图片上传后展示的问题
要展示已上传到Supabase Bucket的图片,核心是获取图片的可访问URL,以下是针对你的代码的具体实现步骤:
1. 确认Bucket权限
首先在Supabase控制台配置avatars桶的访问权限:
- 公共桶:适合公开的头像,创建读取策略允许所有人访问:
CREATE POLICY "允许读取avatars桶的所有文件" ON storage.objects FOR SELECT USING (bucket_id = 'avatars'); - 私有桶:仅允许用户访问自己的头像,创建策略限制读取权限:
CREATE POLICY "用户仅能读取自己的头像" ON storage.objects FOR SELECT USING ( bucket_id = 'avatars' AND auth.uid() = (SELECT user_id FROM users WHERE avatar = name) );
2. 添加获取头像URL的工具函数
在CrudUser.js中添加获取图片URL的函数,根据桶类型选择对应方法:
// 公共桶:获取永久公共URL const getAvatarPublicUrl = (fileName) => { const { data } = supabase.storage.from('avatars').getPublicUrl(fileName); return data.publicUrl; }; // 私有桶:获取临时签名URL(有效期3600秒,可自行调整) const getAvatarSignedUrl = async (fileName) => { const { data } = await supabase.storage.from('avatars').createSignedUrl(fileName, 3600); return data.signedUrl; };
3. 更新用户数据,带上头像URL
修改getUserData函数,在获取用户数据时自动拼接头像URL:
// 公共桶版本 const getUserData = () => { try { supabase.auth.getUser().then(async (value) => { const user = value.data.user; const { data } = await supabase .from("users") .select() .eq("email", user.email); // 为每个用户添加头像URL字段 const usersWithAvatar = data.map(item => ({ ...item, avatarUrl: getAvatarPublicUrl(item.avatar) })); setDb(usersWithAvatar); }); } catch (error) { console.error(error.message); } }; // 私有桶版本(需改为async函数) const getUserData = async () => { try { const authRes = await supabase.auth.getUser(); const user = authRes.data.user; const { data } = await supabase .from("users") .select() .eq("email", user.email); // 异步获取每个用户的签名URL const usersWithAvatar = await Promise.all( data.map(async item => ({ ...item, avatarUrl: await getAvatarSignedUrl(item.avatar) })) ); setDb(usersWithAvatar); } catch (error) { console.error(error.message); } };
4. 在组件中展示头像
4.1 在用户信息区域展示
修改RegisterFormUser.js中的"Your data"部分,添加头像展示:
{dataToEdit || userData.length <= 0 ? ( // 原有表单代码 ) : ( <div> <h3>Your data</h3> {userData.length > 0 && userData[0].avatarUrl && ( <img src={userData[0].avatarUrl} alt="Profile Avatar" style={{ width: '150px', height: '150px', objectFit: 'cover', borderRadius: '50%' }} /> )} <p>姓名: {userData[0].nombres} {userData[0].apellidos}</p> <p>生日: {userData[0].fecha_nacimiento}</p> </div> )}
4.2 上传时实时预览头像
修改RegisterFormUser.js中的handleSelectPicture函数,上传成功后立即展示预览:
const handleSelectPicture = async (e) => { setSelectPicture(e.target.value); const file = e.target.files[0]; form.avatar = file.name; form.infoAvatar = file; try { await uploadAvatar(form); // 上传成功后获取预览URL const { data } = supabase.storage.from('avatars').getPublicUrl(form.avatar); setForm(prev => ({ ...prev, avatarPreviewUrl: data.publicUrl })); } catch (err) { console.error(err); } };
然后在文件选择框下方添加预览区域:
<label> Choose a profile picture</label> <input type="file" id="avatar" name="avatar" accept="image/png, image/jpeg" value={selectPicture} onChange={handleSelectPicture} /> {form.avatarPreviewUrl && ( <img src={form.avatarPreviewUrl} alt="Avatar Preview" style={{ width: '100px', height: '100px', marginTop: '10px', borderRadius: '50%' }} /> )}
内容的提问来源于stack exchange,提问作者Torniceli601
相关产品推荐
相关产品推荐

