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.
Un permis d'écriture est un droit plus large qu'un permis de lecture — dimensionnez-le en conséquence. Quiconque détient l'URL peut écrire ces octets jusqu'à son expiration. Dix minutes est généreux pour une soumission de formulaire ; une heure est déjà long pour un permis que personne ne peut révoquer. Définissez toujours explicitement contentType et maxSize plutôt que d'accepter « tout type, 10 Mo ».
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
- URL signées — le modèle de signature et qui peut signer.
- URL de téléchargement — les jetons de lecture.
- Permissions de bucket —
signUploadest réservé aux administrateurs par défaut. - Opérations sur les fichiers — l'alternative du téléversement multipart.
- Sécurité des téléversements — ce qu'un
PUTdirect valide, et ce qu'il ne valide pas.
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.