BaliseTonSite

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

Verifie tes acquis

5 questions pour valider ce chapitre

1. Qu'est-ce qu'un bucket dans Supabase Storage ?

Valide et sauvegarde ce chapitre

Ne perds pas le fil de ton apprentissage. Chaque QCM terminé sauvegarde ton score. Crée ton profil gratuitement pour débloquer toutes les évaluations du site et retrouver tes résultats plus tard.

Commencer l'aventure
Déjà membre ?Connecte-toi