Skip to main content
Voir en Markdown

Téléversement et signature par lot

Deux problèmes que le seul jeton de téléchargement ne résout pas : faire entrer de gros fichiers dans le stockage sans faire transiter chaque octet par le serveur applicatif, et obtenir beaucoup d'URL à la fois sans un aller-retour par URL.

URL de téléversement

Une URL signée de téléversement est un permis d'écriture à usage unique pour un chemin. Le navigateur y envoie un PUT direct ; votre serveur ne touche jamais les octets.

POST /api/buckets/uploads/sign
Content-Type: application/json
Cookie: <session>

{
  "path": "uploads/user-123/profile-photo.jpg",
  "operation": "upload",
  "expiresIn": 600,
  "contentType": "image/jpeg",
  "maxSize": 5242880
}
{
  "success": true,
  "signedUrl": "https://app.example.com/api/buckets/uploads/signed?path=uploads%2Fuser-123%2Fprofile-photo.jpg&op=upload&expires=1775383800000&token=8c2d…&ct=image%2Fjpeg&max=5242880",
  "expiresAt": "2026-04-05T10:10:00Z",
  "operation": "upload"
}
Champ Type Requis Défaut Remarques
path chaîne Oui La clé exacte à écrire. C'est vous qui la choisissez.
operation chaîne Oui Doit valoir upload ; le défaut est download.
expiresIn entier Non 3600 De 60 à 604800 secondes.
contentType chaîne Non tout type Vérifié lors du PUT.
maxSize entier Non 10485760 (10 Mo) Plafond en octets, vérifié lors du PUT.

Contrairement à un jeton de téléchargement, un jeton de téléversement n'exige pas que le fichier existe — c'est tout l'intérêt. permissions.signUpload détermine qui peut en émettre un, et sa valeur par défaut est « administrateurs uniquement ».

Les contraintes sont signées

contentType et maxSize apparaissent dans la chaîne de requête sous les noms ct et max, et les deux entrent dans la charge utile HMAC. Modifier l'un ou l'autre invalide le jeton : un client ne peut donc pas élargir lui-même le permis qu'on lui a remis.

curl -X PUT "$SIGNED_UPLOAD_URL" \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg
Au moment du PUT Résultat
Dans la fenêtre, type et taille respectés 200 avec { "success": true, "path": … }
Content-Type différent du ct signé 400
Corps plus lourd que le max signé 413
Après expiration, ou paramètre modifié 403
Jeton de téléchargement utilisé en PUT 403 (opération non concordante)

Le fichier stocké atterrit exactement au path signé — aucun préfixe UUID n'est ajouté, contrairement à un téléversement multipart. Vous avez choisi la clé, vous assumez donc les collisions : signer deux fois le même chemin et utiliser les deux permis écrase.

Signature par lot

Une requête, jusqu'à 100 URL. L'usage évident est une galerie dont chaque vignette est privée.

POST /api/buckets/photos/sign/batch
Content-Type: application/json
Cookie: <session>

{
  "files": [
    { "path": "photo-1.jpg", "expiresIn": 3600 },
    { "path": "photo-2.jpg", "expiresIn": 3600 },
    { "path": "uploads/new.jpg", "expiresIn": 600, "operation": "upload" }
  ]
}
{
  "results": [
    { "path": "photo-1.jpg", "signedUrl": "https://…", "expiresAt": "2026-04-05T11:00:00Z" },
    { "path": "photo-2.jpg", "error": "not_found" },
    { "path": "uploads/new.jpg", "signedUrl": "https://…", "expiresAt": "2026-04-05T10:10:00Z" }
  ]
}

Chaque entrée porte son propre expiresIn et sa propre operation. Les entrées de téléchargement dont le fichier manque reviennent avec error: "not_found" au lieu de faire échouer le lot — une galerie comportant une référence morte affiche quand même les quatre-vingt-dix-neuf autres.

Deux choses font en revanche échouer toute la requête : plus de 100 entrées, et un seul expiresIn hors bornes. Les deux répondent 400. L'asymétrie est intentionnelle — un fichier manquant est un état de données que vous pouvez afficher, tandis qu'une expiration invalide est un bogue dans l'appelant.

Pages associées

Dernière mise à jour 27 juillet 2026

Cette documentation a été rédigée avec de l'IA : des erreurs ou du contenu obsolète sont donc possibles. Sovrium est en bêta — les contributions et corrections sont les bienvenues.

Construit avec Sovrium