Expert guide for Supabase Storage including bucket management, file operations, URL generation, and RLS policies...
You are an expert in Supabase Storage, specializing in file management, bucket configuration, access control, and Row Level Security (RLS) policies for storage objects.
Supabase Storage provides S3-compatible object storage with built-in CDN, image transformations, and Row Level Security integration.
Key Components:
const { data, error } = await supabase.storage.createBucket('avatars', {
public: true,
allowedMimeTypes: ['image/*'],
fileSizeLimit: '1MB',
})
insert into storage.buckets (id, name, public)
values ('avatars', 'avatars', true);
Get Bucket:
const { data, error } = await supabase.storage.getBucket('avatars')
List Buckets:
const { data, error } = await supabase.storage.listBuckets()
Update Bucket:
const { data, error } = await supabase.storage.updateBucket('avatars', {
public: false,
allowedMimeTypes: ['image/png', 'image/jpeg'],
fileSizeLimit: '5MB'
})
Delete Bucket:
const { data, error } = await supabase.storage.deleteBucket('avatars')
Empty Bucket:
const { data, error } = await supabase.storage.emptyBucket('avatars')
const avatarFile = event.target.files[0]
const { data, error } = await supabase
.storage
.from('avatars')
.upload('public/avatar1.png', avatarFile, {
cacheControl: '3600',
upsert: false
})
async function uploadAvatar(file: File, userId: string) {
const fileExt = file.name.split('.').pop()
const fileName = `${userId}-${Math.random()}.${fileExt}`
const filePath = `avatars/${fileName}`
const { data, error } = await supabase.storage
.from('avatars')
.upload(filePath, file, {
cacheControl: '3600',
upsert: false,
})
if (error) {
throw new Error(`Upload failed: ${error.message}`)
}
const { data: urlData } = supabase.storage
.from('avatars')
.getPublicUrl(filePath)
return { path: data.path, url: urlData.publicUrl }
}
const { data, error } = await supabase
.storage
.from('avatars')
.download('folder/avatar1.png')
const { data, error } = await supabase
.storage
.from('avatars')
.list('folder', {
limit: 100,
offset: 0,
sortBy: { column: 'name', order: 'asc' }
})
const { data, error } = await supabase
.storage
.from('avatars')
.remove(['folder/avatar1.png', 'folder/avatar2.png'])
const { data } = supabase
.storage
.from('public-bucket')
.getPublicUrl('folder/avatar1.png')
const { data, error } = await supabase
.storage
.from('avatars')
.createSignedUrl('folder/avatar1.png', 60) // 60 seconds
Create Multiple Signed URLs:
const { data, error } = await supabase
.storage
.from('avatars')
.createSignedUrls(['folder/avatar1.png', 'folder/avatar2.png'], 60)
Allow Public Viewing:
create policy "Avatar images are publicly accessible"
on storage.objects for select
using (bucket_id = 'avatars');
Allow Authenticated Uploads:
create policy "Anyone can upload an avatar"
on storage.objects for insert
with check (
bucket_id = 'avatars'
AND auth.role() = 'authenticated'
);
User-Specific Updates:
create policy "Users can update own avatar"
on storage.objects for update
using (
auth.uid()::text = (storage.foldername(name))[1]
AND bucket_id = 'avatars'
);
create policy "Users can access own private files"
on storage.objects for select
using (
bucket_id = 'private-files'
AND auth.uid()::text = (storage.foldername(name))[1]
);
storage.foldername(name)Extracts folder path components from object name.
(storage.foldername('folder1/folder2/file.png'))[1] -- 'folder1'
storage.extension(name)Extracts file extension from object name.
storage.extension('file.png') -- 'png'