Crash Courses · Masters
Storage & File Uploads
Upload, retrieve, and protect files using Supabase Storage.
10 min read+175 XP on completionCert: Supabase Crash Course
Tap any word in the text below to start reading from there.
Storage & File Uploads
Supabase Storage is S3-compatible file storage with bucket-level policies and per-file signed URLs.
Upload a File
import { createClient } from '@/lib/supabase/client'
const supabase = createClient()
async function uploadAvatar(userId: string, file: File) {
const ext = file.name.split('.').pop()
const path = `avatars/${userId}.${ext}`
const { data, error } = await supabase.storage
.from('profiles') // bucket name
.upload(path, file, {
contentType: file.type,
upsert: true, // overwrite if exists
})
if (error) throw new Error(error.message)
return data.path
}Public URL
function getAvatarUrl(path: string) {
const { data } = supabase.storage
.from('profiles')
.getPublicUrl(path)
return data.publicUrl
}
// Usage in Next.js Image
<Image src={getAvatarUrl(user.avatar_path)} alt="Avatar" width={40} height={40} />Signed URL (Private Bucket)
async function getCertificateUrl(path: string) {
const { data, error } = await supabase.storage
.from('certificates') // private bucket
.createSignedUrl(path, 3600) // expires in 1 hour
if (error) throw error
return data.signedUrl
}File Input + Upload Component
'use client'
export function FileUpload({ onUpload }: { onUpload: (url: string) => void }) {
async function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
const file = e.target.files?.[0]
if (!file) return
const path = await uploadAvatar(userId, file)
const url = getAvatarUrl(path)
onUpload(url)
}
return (
<input
type="file"
accept="image/*"
onChange={handleChange}
className="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-lg file:bg-amber-50 file:text-amber-700"
/>
)
}Reading progress
0% read
In this module
Bucket
upload()
getPublicUrl()
createSignedUrl()
0%