Fichiers et Relations dans PocketBase : Stockage S3, Thumbnails et Expansions en 2026

Fichiers et Relations dans PocketBase : Stockage S3, Thumbnails et Expansions en 2026

PocketBase est un outil backend open-source qui simplifie la gestion des données pour les petites entreprises et les startups. Parmi ses forces, la manipulation de fichiers et les relations entre enregistrements se distinguent par leur simplicité et leur efficacité. Dans cet article, nous explorons ces fonctionnalités en détail. Vous apprendrez à uploader des images, PDFs ou avatars, à les stocker localement ou sur S3, à générer des miniatures automatiques, à sécuriser les accès avec des tokens, et à créer des bases de données relationnelles avec des expansions et des back-relations. Tout cela s'appuie sur la documentation officielle de PocketBase, sans ajouts superflus.

Cet article s'adresse aux débutants comme aux équipes en croissance qui cherchent à implémenter des fonctionnalités robustes sans complexité excessive. Nous utilisons des exemples concrets en JavaScript et Dart, les SDK les plus courants pour PocketBase. Prêts ? Allons-y étape par étape.

1. Upload et Thumbnails Automatiques : Les Bases de la Gestion de Fichiers

Commençons par l'upload de fichiers, une opération courante pour les applications sociales, e-commerce ou CMS. Dans PocketBase, les fichiers ne sont pas gérés isolément : ils sont attachés à des enregistrements (records) dans une collection. Pour activer cela, ajoutez un champ de type "file" à votre collection via l'interface admin (Dashboard).

Comment Ajouter un Champ File

  • Ouvrez le Dashboard de PocketBase (généralement sur http://127.0.0.1:8090/_/).
  • Sélectionnez une collection existante ou en créez une nouvelle.
  • Dans l'onglet "Schema", cliquez sur "Add field" et choisissez "File".
  • Configurez les options : nom du champ (ex. : "avatar"), max size (défaut 5MB, jusqu'à 8GB), max files (1 pour single, plus pour multiple), et activez "Thumb sizes" si vous voulez des miniatures (ex. : 100x100, 300x300).

Une fois configuré, l'upload se fait via l'API Records (create ou update), en envoyant une requête multipart/form-data. PocketBase stocke le fichier avec un nom sanitizé + un suffixe aléatoire (ex. : avatar_abc123def.jpg) pour éviter les collisions.

Exemple d'Upload Simple en JavaScript

Utilisez le SDK officiel pour une intégration fluide. Installez-le via npm : npm install pocketbase.

import PocketBase from 'pocketbase';

const pb = new PocketBase('http://127.0.0.1:8090');

// Créer un record avec un fichier
const formData = new FormData();
formData.append('name', 'Utilisateur Test');
const fileInput = document.getElementById('avatarInput'); // Élément HTML <input type="file">
if (fileInput.files[0]) {
  formData.append('avatar', fileInput.files[0]);
}

try {
  const record = await pb.collection('users').create(formData);
  console.log('Record créé avec fichier:', record);
} catch (error) {
  console.error('Erreur upload:', error);
}

Ici, le fichier est uploadé lors de la création du record. Pour des uploads multiples (si max files > 1), ajoutez plusieurs fichiers au FormData avec la même clé.

Génération de Thumbnails Automatiques

Si "Thumb sizes" est activé, PocketBase génère des miniatures pour les images (JPG, PNG, GIF, WebP partiel). Les formats supportés incluent :

  • WxH : Crop au centre vers WxH pixels.
  • WxHt : Crop depuis le haut.
  • WxHf : Fit sans crop.
  • Wx0 : Resize à la largeur W, aspect ratio préservé.

Accédez à une miniature en ajoutant ?thumb=100x100 à l'URL du fichier :

http://127.0.0.1:8090/api/files/users/RECORD_ID/avatar_abc123def.jpg?thumb=100x100

Avec le SDK :

const record = await pb.collection('users').getOne('RECORD_ID');
const url = pb.files.getUrl(record, record.avatar, { thumb: '100x100' });
console.log('URL miniature:', url);

Pour les startups, cela signifie des avatars ou images produits optimisés sans effort supplémentaire. Les thumbnails sont générées à la demande et mises en cache pour les performances.

Limites et Bonnes Pratiques

  • Taille max : 8GB par fichier, mais commencez par 5-10MB pour éviter les abus.
  • Formats : Tout fichier binaire, mais thumbnails seulement pour images.
  • Erreurs courantes : Vérifiez les règles d'API (ex. : @request.auth.id != '' pour uploads authentifiés).

En production, surveillez l'espace disque. Nous y reviendrons avec S3.

2. Stockage Local vers S3 : Évoluez Sans Limites

Par défaut, PocketBase stocke les fichiers dans pb_data/storage sur le serveur local. C'est rapide et simple pour les tests ou petites apps, mais pour une startup en croissance, l'espace disque peut vite devenir un goulot.

Configuration du Stockage Local

Aucun setup requis : les fichiers atterrissent directement dans le dossier. Pour les backups, copiez simplement pb_data. Idéal pour les SMB avec un VPS basique.

Migration vers S3 : Scalabilité Facile

Pour du stockage cloud scalable (AWS S3, MinIO, DigitalOcean Spaces), configurez via le Dashboard :

  • Allez dans Settings > Files storage.
  • Choisissez "S3" comme provider.
  • Entrez : Endpoint (ex. : https://s3.amazonaws.com), Bucket, Access Key, Secret Key, Region.
  • Optionnel : Custom domain pour les URLs CDN.

Une fois configuré, tous les nouveaux uploads partent sur S3. Les fichiers existants restent locaux – migrez-les manuellement via un script Go si besoin.

Exemple de Configuration S3 en Production

Dans un fichier .env pour Docker :

PB_PUBLIC_BUCKET_URL=https://mon-bucket.s3.eu-west-1.amazonaws.com
PB_S3_ENDPOINT=https://s3.eu-west-1.amazonaws.com
PB_S3_ACCESS_KEY_ID=your_key
PB_S3_SECRET_ACCESS_KEY=your_secret
PB_S3_BUCKET=your_bucket
PB_S3_REGION=eu-west-1

Relancez PocketBase pour appliquer. Les URLs des fichiers deviennent :

https://mon-bucket.s3.eu-west-1.amazonaws.com/users/RECORD_ID/avatar_abc123def.jpg

Pour les e-commerce, cela signifie des images produits infinies sans saturation du serveur. Coût : ~0.02€/GB/mois sur AWS, parfait pour startups.

Intégration avec le SDK

Aucun changement côté code : le SDK gère les URLs automatiquement. Testez avec un upload comme ci-dessus – vérifiez sur S3 que le fichier arrive.

Astuce pour débutants : Utilisez MinIO pour tester localement (self-hosted S3-compatible).

3. Tokens de Téléchargement Sécurisés : Protégez Vos Données Sensibles

Tous les fichiers sont publics par défaut si l'URL est connue. Pratique pour des images publiques, mais risqué pour des PDFs contrats ou avatars privés.

Marquer un Champ comme Protégé

Dans le Dashboard :

  • Éditez le champ file.
  • Cochez "Protected".
  • Définissez une règle View API (ex. : @request.auth.id = owner.id pour accès propriétaire seulement).

Seuls les utilisateurs satisfaisant la règle peuvent générer un token.

Génération et Utilisation des Tokens

Les tokens expirent en ~2 minutes. Générez-en un via l'API ou SDK après authentification.

Endpoint : POST /api/files/token (auth required).

Avec SDK JS :

// Authentifiez d'abord
await pb.collection('users').authWithPassword('[email protected]', 'password');

// Générez le token
const token = await pb.files.getToken();

// Récupérez le record et construisez l'URL
const record = await pb.collection('users').getOne('RECORD_ID');
const url = pb.files.getUrl(record, record.privateFile, { token: token });
console.log('URL sécurisée:', url);

Pour download forcé : Ajoutez ?download=1.

En Dart, similaire :

await pb.collection('users').authWithPassword('[email protected]', 'password');
final token = await pb.files.getToken();
final record = await pb.collection('users').getOne('RECORD_ID');
final url = pb.files.getUrl(record, record.getStringValue('privateFile'), token: token);

Cas d'Usage pour SMB

Dans un CMS, protégez les documents clients. Dans une app sociale, limitez les avatars aux amis. Les tokens courts évitent les fuites même si une URL est partagée temporairement.

Erreurs : 403 si token invalide ou règle non respectée. Toujours authentifier avant.

4. Relations 1-n et n-n : Structurez Vos Données

PocketBase excelle dans les relations sans boilerplate SQL. Ajoutez un champ "relation" à une collection pour lier à une autre.

Configuration des Relations

  • Champ type "Relation".
  • Options : Collection cible (ex. : "tags" pour posts), single/multiple (1-n ou n-n), auto-expand (pour inclure les données liées).

Exemple : Collection "posts" avec champ "tags" (multiple relation vers "tags").

Créer des Relations

Lors de create/update, passez l'ID (single) ou array d'IDs (multiple).

JS :

const post = await pb.collection('posts').create({
  title: 'Mon article',
  tags: ['tag_id_1', 'tag_id_2']  // n-n
});

Pour 1-n (ex. : post a un author) :

const post = await pb.collection('posts').create({
  title: 'Mon article',
  author: 'user_id_123'  // single
});

Modificateurs + et - pour Mises à Jour Incrémentales

Évitez de recharger tout l'array : utilisez + pour ajouter, - pour supprimer.

Ajouter (append) :

await pb.collection('posts').update('post_id', {
  'tags+': ['new_tag_id']  // Ajoute à la fin
});

Préfixe pour prepend :

await pb.collection('posts').update('post_id', {
  '+tags': ['new_tag_id']  // Ajoute au début
});

Supprimer :

await pb.collection('posts').update('post_id', {
  'tags-': ['old_tag_id']
});

Pratique pour e-commerce : Ajoutez des produits à une catégorie sans tout revalider.

5. Expand et Back-Relations : Récupérez des Données Efficacement

Expansions : Incluez les Relations en Une Requête

Évitez les N+1 queries avec ?expand=relation. Supporte nested (jusqu'à 6 niveaux).

JS :

const posts = await pb.collection('posts').getList(1, 10, {
  expand: 'author,tags'  // Inclut author et tags
});
console.log(posts.items[0].expand);  // Données liées ici

Seules les relations visibles (via View rule) s'expansent. Limite : 1000 records par relation pour éviter les surcharges.

Back-Relations : Naviguez Inversement

Pour queries du parent vers enfants (ex. : posts avec comments contenant "hello").

Syntaxe : collection_via_field (ex. : comments_via_post).

Filtre :

const posts = await pb.collection('posts').getList(1, 10, {
  filter: "comments_via_post.message ?~ 'hello'",
  expand: 'comments_via_post'
});

Back-relations sont toujours multiple, sauf si unique index. Limite expand : 1000. Pour plus, paginez avec getList sur la collection enfant.

Exemple pour app sociale : Récupérez un user avec ses posts et comments liés.

Astuces 2025 : Pas de changements majeurs, mais optimisez avec sort sur back-relations pour les dashboards.

Exemple Complet : App E-Commerce Simple

Imaginons une collection "products" (avec champ "images" multiple file, protégé) liée à "categories" (relation multiple).

  1. Créez la collection products avec champs : name, price, images (file, protected, thumbs 300x300), categories (relation multiple vers categories).
  2. Upload produit :
const formData = new FormData();
formData.append('name', 'Chaussure Nike');
formData.append('price', '99.99');
formData.append('categories', ['cat_shoes_id']);
const file = fileInput.files[0];
formData.append('images', file);

const product = await pb.collection('products').create(formData);
  1. Récupérez avec expand et back-relations (ex. : orders pour ce product) :
const product = await pb.collection('products').getOne(product.id, {
  expand: 'categories,orders_via_product'
});

// Générez URL thumb sécurisée
await pb.collection('users').authWithPassword(...);
const token = await pb.files.getToken();
const thumbUrl = pb.files.getUrl(product, product.images[0], { thumb: '300x300', token });
  1. Ajoutez image : images+ avec nouveau FormData.

Pour S3 : Configurez avant, et les images partent direct.

Testez en local, déployez sur un VPS avec Docker pour scaler.

Bonnes Pratiques pour Débutants et Startups

  • Sécurité : Toujours protéger les champs sensibles. Utilisez MFA pour admins.
  • Performances : Limitez expands à l'essentiel. Pour gros volumes, query paginé.
  • Stockage : Local pour dev, S3 pour prod. Backup automatique via cron sur pb_data ou S3 lifecycle.
  • Erreurs : Vérifiez 413 (trop gros), 403 (accès). Logs dans Dashboard.
  • Intégration Frontend : Avec React/Vue, utilisez le SDK pour uploads drag-drop.
  • Coûts : S3 gratuit jusqu'à 5GB, puis scalable. PocketBase reste gratuit.

Pour une startup, commencez par local + relations simples, migrez vers S3 au premier pic de trafic.

Conclusion

La gestion de fichiers et relations dans PocketBase offre un équilibre parfait entre simplicité et puissance. Vous pouvez uploader des médias avec thumbnails, les sécuriser via tokens, les stocker sur S3, et lier des données avec expansions efficaces – tout en un fichier exécutable. Pour les SMB et startups, cela accélère le MVP sans vendor lock-in.

Testez ces exemples dans votre instance locale. Si vous rencontrez des blocages, consultez la doc officielle ou les forums. Prochain article : APIs realtime pour des apps dynamiques.

Lire la suite