Supabase存储桶管理 #
一、创建存储桶 #
1.1 使用Dashboard创建 #
text
Dashboard > Storage > Create a new bucket
配置项
├── Name: 存储桶名称
│ └── 只能包含小写字母、数字、连字符
│
├── Public bucket: 是否公开
│ └── 公开桶任何人都可以读取
│
├── File size limit: 文件大小限制
│ └── 例如: 1MB, 5MB, 10MB
│
└── Allowed MIME types: 允许的文件类型
└── 例如: image/*, application/pdf
1.2 使用API创建 #
typescript
// 创建公开存储桶
const { data, error } = await supabase.storage.createBucket('avatars', {
public: true,
fileSizeLimit: 1024 * 1024, // 1MB
allowedMimeTypes: ['image/png', 'image/jpeg', 'image/gif'],
})
// 创建私有存储桶
const { data, error } = await supabase.storage.createBucket('documents', {
public: false,
fileSizeLimit: 10 * 1024 * 1024, // 10MB
})
1.3 使用SQL创建 #
sql
-- 插入存储桶记录
INSERT INTO storage.buckets (id, name, public)
VALUES ('avatars', 'avatars', true);
二、存储桶配置 #
2.1 更新存储桶配置 #
typescript
// 更新存储桶设置
const { data, error } = await supabase.storage.updateBucket('avatars', {
public: true,
fileSizeLimit: 2 * 1024 * 1024, // 2MB
allowedMimeTypes: ['image/*'],
})
2.2 获取存储桶信息 #
typescript
// 获取所有存储桶
const { data, error } = await supabase.storage.listBuckets()
// 获取单个存储桶
const { data, error } = await supabase.storage.getBucket('avatars')
2.3 清空存储桶 #
typescript
// 清空存储桶所有文件
const { data, error } = await supabase.storage.emptyBucket('temp-uploads')
2.4 删除存储桶 #
typescript
// 删除存储桶(必须先清空)
await supabase.storage.emptyBucket('old-bucket')
const { data, error } = await supabase.storage.deleteBucket('old-bucket')
三、权限策略配置 #
3.1 公开读取策略 #
sql
-- 允许所有人读取
CREATE POLICY "Public Read Access"
ON storage.objects FOR SELECT
USING (bucket_id = 'avatars');
3.2 认证用户上传策略 #
sql
-- 只有认证用户可以上传
CREATE POLICY "Authenticated users can upload"
ON storage.objects FOR INSERT
WITH CHECK (
bucket_id = 'uploads' AND
auth.role() = 'authenticated'
);
3.3 用户文件隔离策略 #
sql
-- 用户只能访问自己文件夹下的文件
CREATE POLICY "Users can access own files"
ON storage.objects FOR ALL
USING (
bucket_id = 'user-files' AND
auth.uid()::text = (storage.foldername(name))[1]
);
-- 解释:
-- storage.foldername(name) 返回路径的文件夹数组
-- [1] 获取第一个文件夹名(用户ID)
-- auth.uid()::text 转换当前用户ID为文本
3.4 完整权限策略示例 #
sql
-- 为user-uploads桶设置完整策略
-- 1. 用户可以查看自己的文件
CREATE POLICY "Users can view own files"
ON storage.objects FOR SELECT
USING (
bucket_id = 'user-uploads' AND
auth.uid()::text = (storage.foldername(name))[1]
);
-- 2. 用户可以上传文件到自己的文件夹
CREATE POLICY "Users can upload to own folder"
ON storage.objects FOR INSERT
WITH CHECK (
bucket_id = 'user-uploads' AND
auth.uid()::text = (storage.foldername(name))[1]
);
-- 3. 用户可以更新自己的文件
CREATE POLICY "Users can update own files"
ON storage.objects FOR UPDATE
USING (
bucket_id = 'user-uploads' AND
auth.uid()::text = (storage.foldername(name))[1]
);
-- 4. 用户可以删除自己的文件
CREATE POLICY "Users can delete own files"
ON storage.objects FOR DELETE
USING (
bucket_id = 'user-uploads' AND
auth.uid()::text = (storage.foldername(name))[1]
);
四、常见存储桶配置 #
4.1 头像存储桶 #
sql
-- 创建头像存储桶
INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
VALUES (
'avatars',
'avatars',
true,
1048576, -- 1MB
ARRAY['image/png', 'image/jpeg', 'image/gif', 'image/webp']
);
-- 权限策略
CREATE POLICY "Anyone can view avatars"
ON storage.objects FOR SELECT
USING (bucket_id = 'avatars');
CREATE POLICY "Users can upload own avatar"
ON storage.objects FOR INSERT
WITH CHECK (
bucket_id = 'avatars' AND
auth.uid()::text = (storage.foldername(name))[1]
);
CREATE POLICY "Users can update own avatar"
ON storage.objects FOR UPDATE
USING (
bucket_id = 'avatars' AND
auth.uid()::text = (storage.foldername(name))[1]
);
4.2 文档存储桶 #
sql
-- 创建文档存储桶
INSERT INTO storage.buckets (id, name, public, file_size_limit)
VALUES (
'documents',
'documents',
false,
10485760 -- 10MB
);
-- 权限策略
CREATE POLICY "Users can manage own documents"
ON storage.objects FOR ALL
USING (
bucket_id = 'documents' AND
auth.uid()::text = (storage.foldername(name))[1]
);
4.3 产品图片存储桶 #
sql
-- 创建产品图片存储桶
INSERT INTO storage.buckets (id, name, public)
VALUES ('product-images', 'product-images', true);
-- 管理员可以管理所有图片
CREATE POLICY "Admins can manage all product images"
ON storage.objects FOR ALL
USING (
bucket_id = 'product-images' AND
EXISTS (
SELECT 1 FROM profiles
WHERE id = auth.uid() AND role = 'admin'
)
);
-- 所有人可以查看
CREATE POLICY "Anyone can view product images"
ON storage.objects FOR SELECT
USING (bucket_id = 'product-images');
五、使用Dashboard管理策略 #
5.1 策略编辑器 #
text
Dashboard > Storage > [Bucket] > Policies
功能
├── 查看现有策略
├── 创建新策略
├── 编辑策略
├── 删除策略
└── 使用模板
5.2 策略模板 #
text
Dashboard提供常用模板
├── Allow public read access
├── Allow authenticated read access
├── Allow public upload
├── Allow authenticated upload
├── Allow user to read own files
├── Allow user to upload to own folder
└── Allow user to update own files
六、存储桶管理函数 #
6.1 检查存储桶是否存在 #
typescript
async function bucketExists(name: string): Promise<boolean> {
const { data, error } = await supabase.storage.getBucket(name)
return !error && !!data
}
6.2 获取存储桶统计 #
typescript
async function getBucketStats(bucketName: string) {
const { data: files, error } = await supabase.storage
.from(bucketName)
.list()
if (error) return null
const totalSize = files?.reduce((sum, file) =>
sum + (file.metadata?.size || 0), 0
) || 0
return {
fileCount: files?.length || 0,
totalSize,
totalSizeMB: (totalSize / 1024 / 1024).toFixed(2),
}
}
6.3 批量创建存储桶 #
typescript
async function setupBuckets() {
const buckets = [
{ name: 'avatars', public: true, limit: 1024 * 1024 },
{ name: 'documents', public: false, limit: 10 * 1024 * 1024 },
{ name: 'images', public: true, limit: 5 * 1024 * 1024 },
]
for (const bucket of buckets) {
const exists = await bucketExists(bucket.name)
if (!exists) {
await supabase.storage.createBucket(bucket.name, {
public: bucket.public,
fileSizeLimit: bucket.limit,
})
}
}
}
七、错误处理 #
7.1 常见错误 #
typescript
const errorMessages: Record<string, string> = {
'Bucket not found': '存储桶不存在',
'Bucket already exists': '存储桶已存在',
'Invalid bucket name': '存储桶名称无效',
'storage quota exceeded': '存储配额已满',
'File size exceeded': '文件大小超限',
'Invalid mime type': '文件类型不允许',
}
function handleStorageError(error: any): string {
return errorMessages[error.message] || error.message
}
八、最佳实践 #
8.1 存储桶命名规范 #
text
命名建议
├── 使用小写字母
├── 使用连字符分隔
├── 简短有意义
└── 示例: avatars, user-documents, product-images
8.2 权限设计原则 #
text
权限设计原则
├── 最小权限原则
├── 按需开放访问
├── 用户数据隔离
├── 敏感文件私有
└── 公开资源只读
九、总结 #
存储桶管理要点:
| 操作 | 方法 |
|---|---|
| 创建 | createBucket(name, options) |
| 更新 | updateBucket(name, options) |
| 获取 | getBucket(name) |
| 列出 | listBuckets() |
| 清空 | emptyBucket(name) |
| 删除 | deleteBucket(name) |
下一步,让我们学习文件上传下载!
最后更新:2026-03-28