85 lines
2.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 文件存储
## 创建存储桶
通过 SQL 迁移创建存储桶:
```sql
INSERT INTO storage.buckets (id, name, public)
VALUES ('avatars', 'avatars', true);
```
## 关键上传方法
**必须使用 ArrayBuffer**(通过 `base64-arraybuffer`)进行所有文件上传。使用 `Blob``File``FormData` 会导致 `400 InvalidRequest "No content provided"` 错误。
**注意**:必须通过友好的 Toast 交互提醒用户数据操作结果,特别是操作失败的情况。
**重要约束必须在前端上传文件。禁止在云函数Edge Functions中上传文件**,因为云函数上传的文件无法获取公网访问 URL会导致前端无法正常访问和显示文件。所有文件上传操作必须在前端浏览器环境中进行。
> 记得在 `package.json` 中添加 `base64-arraybuffer` 依赖。
```typescript
import { decode } from 'base64-arraybuffer';
// ✅ 从 base64 字符串上传(必须检查 error
const { data, error } = await supabase.storage
.from('avatars')
.upload('public/avatar1.png', decode('base64FileData'), {
contentType: 'image/png'
});
if (error) throw new Error(`上传失败: ${error.message}`);
// 从文件输入上传(先转换为 ArrayBuffer
const reader = new FileReader();
reader.onload = async (e) => {
const base64 = (e.target?.result as string).split(',')[1];
const { data, error } = await supabase.storage
.from('bucket-name')
.upload(`path/${file.name}`, decode(base64), {
contentType: file.type,
});
if (error) {
console.error('上传失败:', error.message);
return;
}
};
reader.readAsDataURL(file);
```
```typescript
// ❌ 错误做法 — 会导致 400 错误
const formData = new FormData();
formData.append('file', file);
await supabase.storage.from('bucket').upload('path', formData); // ❌
await supabase.storage.from('bucket').upload('path', blob); // ❌
await supabase.storage.from('bucket').upload('path', file); // ❌
```
## 存储 RLS 策略
```sql
-- 创建存储桶的 RLS 策略
CREATE POLICY anon_select_avatars ON storage.objects
FOR SELECT USING (bucket_id = 'avatars');
CREATE POLICY users_insert_avatars ON storage.objects
FOR INSERT WITH CHECK (
bucket_id = 'avatars' AND
auth.role() = 'authenticated'
);
```
## Edge Functions 存储限制
**重要**:存储操作应在前端执行,而非 Edge Functions。Edge Functions 使用私有网络 URL无法提供文件的公开访问。
## 存储模式限制
不要在 `storage` 模式中执行以下操作:
- 创建自定义表或函数
- 删除现有表或函数
- 在现有存储表上创建索引
-`storage.migrations` 执行破坏性操作
管理文件访问请在 `public` 模式中创建辅助函数。