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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 20:27:36