# Stockage des médias en base de données (DB Storage) ## Contexte Sur les plateformes PaaS (Scalingo, Heroku, Clever Cloud) ou les déploiements Docker, le système de fichiers est souvent **éphémère** : chaque redéploiement efface les fichiers uploadés (images, documents). Pour qu’ils ne disparaissent pas, vous avez besoin de les mettre dans un backend de stockage. Sites Conformes propose trois backends de stockage pour les médias : | Backend | Variable d’activation | Cas d’usage | | ------- | --------------------- | ----------- | | **Système de fichiers** | _(par défaut)_ | Développement local, VPS, hébergement dédié | | **S3** (Object Storage) | `S3_HOST` | Production avec stockage S3 compatible | | **PostgreSQL** (DB Storage) | `SF_USE_DB_STORAGE=1` | PaaS sans S3, Docker, Plesk | Les commandes de migration disponibles couvrent tous les trajets possibles entre ces backends : | Commande | Trajet | | -------- | ------ | | `migrate_files_to_db` | Système de fichiers → DB | | `migrate_db_to_files` | DB → Système de fichiers | | `migrate_s3_to_db` | S3 → DB | | `migrate_db_to_s3` | DB → S3 | :::{warning} **Ce mode de stockage n’est pas recommandé au-delà de 1 Go de médias.** Pour les sites avec beaucoup d’images ou de documents, préférez un stockage S3 compatible. Au-delà de cette limite, les performances se dégradent (temps de réponse, sauvegardes, consommation mémoire). ::: ## Fonctionnement - Les fichiers sont stockés dans la table `db_storage_storedfile` sous forme binaire (`BinaryField`). - Les images et documents uploadés via l’admin Wagtail sont automatiquement sauvegardés en base. - Les fichiers sont servis via l’URL `/db-storage/serve/?name=`. - Un header `Cache-Control: public, max-age=3600` est appliqué pour le cache navigateur. ## Activation Ajoutez dans vos variables d’environnement (Dans Scalingo : onglet Environnement > Nouvelle variable ) : ```text SF_USE_DB_STORAGE=1 ``` Puis relancez l’application. Les médias seront stockés directement dans la base de données PostgreSQL. :::{note} **Note** : Si `S3_HOST` est configuré, le S3 est prioritaire et `SF_USE_DB_STORAGE` est ignoré. Si vous utilisiez déjà un S3, il faudra d’abord suivre la procédure « Migration depuis un S3 » ci-dessous avant de retirer la variable `S3_HOST`. ::: ## Migration depuis S3 Si vous utilisez actuellement S3 et souhaitez passer au stockage en base de données : ### 1. Transférer les fichiers Après l’activation de `SF_USE_DB_STORAGE` (cf. ci-dessus), et avec les variables `S3_xxx` encore configurées, se connecter à l’app en ligne de commande (cf [Documentation de Scalingo](https://doc.scalingo.com/tools/cli/start)) ```sh python manage.py migrate_s3_to_db ``` Cette commande : - Se connecte au bucket S3 avec les credentials définis dans les variables d’environnement - Télécharge tous les fichiers et les stocke dans la table `StoredFile` - Met à jour les éventuelles URLs S3 codées en dur dans les révisions Wagtail et les champs texte ### 2. Options disponibles ```sh # Simulation sans modification python manage.py migrate_s3_to_db --dry-run # Transférer uniquement les fichiers (sans mise à jour des URLs) python manage.py migrate_s3_to_db --skip-urls # Mettre à jour uniquement les URLs (fichiers déjà transférés) python manage.py migrate_s3_to_db --skip-files ``` ### 3. Basculer le backend Une fois les fichiers transférés, modifiez vos variables d’environnement (Dans Scalingo : onglet Environnement > Modifier en masse ) : - Supprimer ou vider `S3_HOST` et les autres variables dont le nom commencent par `S3_`. Redémarrez l’application. Les images et documents s’afficheront depuis la base de données. ## Migration depuis le système de fichiers Si vos médias sont sur le système de fichiers local : ```sh python manage.py migrate_files_to_db ``` Options : - `--dry-run` : simule la migration sans modifier la base ## Migration depuis la DB vers le système de fichiers Si vous souhaitez quitter le stockage en base et revenir au système de fichiers : ```sh python manage.py migrate_db_to_files ``` Cette commande : - Écrit chaque fichier de la table `StoredFile` dans `MEDIA_ROOT` en recréant l’arborescence - Ignore les fichiers déjà présents sur le filesystem (par chemin) - Met à jour les URLs `/db-storage/serve?name=…` codées en dur vers `MEDIA_URL` Options : ```sh # Simulation sans modification python manage.py migrate_db_to_files --dry-run # Transférer uniquement les fichiers (sans mise à jour des URLs) python manage.py migrate_db_to_files --skip-urls # Mettre à jour uniquement les URLs (fichiers déjà transférés) python manage.py migrate_db_to_files --skip-files ``` Après la migration, désactivez le DB storage dans votre `.env` : ```text SF_USE_DB_STORAGE=0 ``` ## Migration depuis la DB vers S3 Si votre volume de médias dépasse 1 Go ou que vous souhaitez passer à S3 : ```sh python manage.py migrate_db_to_s3 ``` Cette commande : - Lit tous les fichiers stockés dans la table `StoredFile` - Les uploade vers le bucket S3 configuré dans votre `.env` - Ignore les fichiers déjà présents sur S3 (par nom) Options : ```sh # Simulation sans modification python manage.py migrate_db_to_s3 --dry-run ``` Après la migration, modifiez votre `.env` pour désactiver le DB storage : ```text SF_USE_DB_STORAGE=0 S3_HOST=s3.example.com # ... autres variables S3 ``` ## Limitations - **Volume maximum recommandé : 1 Go.** Au-delà, les performances se dégradent sensiblement (temps de réponse, sauvegardes, consommation mémoire). Préférez S3 pour les sites avec beaucoup de médias. - **Taille de la base** : Les fichiers augmentent la taille de la base PostgreSQL et donc des sauvegardes. - **Trafic** : Chaque fichier devant être servi par Django, il est déconseillé de l’utiliser sur les sites à fort trafic. - **Pas de CDN** : Contrairement au S3, les fichiers ne bénéficient pas d’un CDN. Le header `Cache-Control` permet toutefois la mise en cache côté navigateur. ## Architecture technique ```text db_storage/ ├── models.py # Modèle StoredFile (BinaryField) ├── storage.py # Backend DatabaseStorage (API Django Storage) ├── views.py # Vue de service des fichiers ├── urls.py # Route /db-storage/serve/ └── management/commands/ ├── migrate_files_to_db.py # Migration filesystem → DB ├── migrate_db_to_files.py # Migration DB → filesystem ├── migrate_s3_to_db.py # Migration S3 → DB └── migrate_db_to_s3.py # Migration DB → S3 ```