Storage
Upload de fichiers, gestion des buckets, policies de sécurité et URLs signées.
7.1Créer un bucket
Un bucket est un conteneur de fichiers. Tu peux le créer via le dashboard (Storage → New Bucket) ou par code :
Créer un buckettypescript
// Bucket public (images accessibles via URL directe)
const { data, error } = await supabase.storage
.createBucket('avatars', {
public: true,
fileSizeLimit: 1024 * 1024 * 2, // 2 Mo max
allowedMimeTypes: ['image/png', 'image/jpeg', 'image/webp'],
})
// Bucket privé (nécessite une URL signée pour accéder)
const { data: privateBucket } = await supabase.storage
.createBucket('documents', {
public: false,
})7.2Upload de fichiers
Upload depuis un formulaire Reacttypescript
function AvatarUpload({ userId }: { userId: string }) {
async function handleUpload(e: React.ChangeEvent<HTMLInputElement>) {
const file = e.target.files?.[0]
if (!file) return
const filePath = `${userId}/avatar.${file.name.split('.').pop()}`
const { data, error } = await supabase.storage
.from('avatars')
.upload(filePath, file, {
cacheControl: '3600', // Cache 1h
upsert: true, // Remplace si existe déjà
})
if (error) {
console.error('Erreur upload :', error.message)
return
}
console.log('Fichier uploadé :', data.path)
}
return (
<input
type="file"
accept="image/png, image/jpeg, image/webp"
onChange={handleUpload}
/>
)
}7.3Récupérer les fichiers
URL publique vs URL signéetypescript
// URL publique (bucket public)
const { data } = supabase.storage
.from('avatars')
.getPublicUrl('user123/avatar.jpg')
console.log(data.publicUrl)
// https://xxxx.supabase.co/storage/v1/object/public/avatars/user123/avatar.jpg
// URL signée (bucket privé) - expire après 1h
const { data: signed, error } = await supabase.storage
.from('documents')
.createSignedUrl('user123/facture.pdf', 3600) // 3600 secondes = 1h
console.log(signed?.signedUrl)
// https://xxxx.supabase.co/storage/v1/object/sign/documents/user123/facture.pdf?token=...7.4Lister et supprimer
Lister les fichiers d'un dossiertypescript
// Lister les fichiers dans un dossier
const { data: files, error } = await supabase.storage
.from('avatars')
.list('user123', {
limit: 100,
offset: 0,
sortBy: { column: 'created_at', order: 'desc' },
})
// files = [{ name: 'avatar.jpg', id: '...', metadata: { size: 12345 } }]Supprimer des fichierstypescript
// Supprimer un fichier
const { error } = await supabase.storage
.from('avatars')
.remove(['user123/avatar.jpg'])
// Supprimer plusieurs fichiers
const { error: err } = await supabase.storage
.from('documents')
.remove([
'user123/facture-01.pdf',
'user123/facture-02.pdf',
])7.5Policies Storage
Les policies Storage fonctionnent comme RLS mais pour les fichiers. Tu les configures dans Storage → Policies :
Policies Storage courantesbash
-- Chaque utilisateur peut uploader dans son propre dossier
CREATE POLICY "users can upload their own avatar"
ON storage.objects FOR INSERT
WITH CHECK (
bucket_id = 'avatars'
AND auth.uid()::text = (storage.foldername(name))[1]
);
-- Chaque utilisateur peut voir ses propres fichiers
CREATE POLICY "users can view their own files"
ON storage.objects FOR SELECT
USING (
bucket_id = 'documents'
AND auth.uid()::text = (storage.foldername(name))[1]
);
-- Tout le monde peut voir les avatars (bucket public)
CREATE POLICY "public can view avatars"
ON storage.objects FOR SELECT
USING (bucket_id = 'avatars');
-- Les utilisateurs peuvent supprimer leurs propres fichiers
CREATE POLICY "users can delete own files"
ON storage.objects FOR DELETE
USING (
auth.uid()::text = (storage.foldername(name))[1]
);7.6Transformation d'images
Redimensionner à la voléetypescript
// Supabase peut transformer les images à la volée
const { data } = supabase.storage
.from('avatars')
.getPublicUrl('user123/avatar.jpg', {
transform: {
width: 200,
height: 200,
resize: 'cover', // Comme object-fit: cover en CSS
quality: 80, // Compression JPEG
},
})
// L'image originale n'est pas modifiée, la transformation est en cache CDN