Gros fichiers
Au-delà de DROP_MAX_SIZE_MB, le navigateur envoie le fichier directement au bucket, en morceaux, avec reprise. La règle CORS et le nettoyage qu’il faut.
Une fonction Vercel accepte au plus 4,5 Mo par requête. La page de livraison contourne cette limite
sans rien faire passer par la fonction : au-delà de DROP_MAX_SIZE_MB (4 par défaut), le navigateur
envoie le fichier lui-même au bucket, en morceaux, par des URL présignées. Le serveur ne fait que
signer et assembler. La taille maximale acceptée est DROP_MAX_UPLOAD_MB, 2 048 Mo par défaut.
Comment ça se passe
POST /api/transfers/uploadsavec{ filename, size, contentType }et les mêmes options que le formulaire (expiresIn,passphrase,note,device,oneTime). Le serveur tire un code, ouvre un envoi multipart sur la clé finale du colis, et garde le tout dans un enregistrementmeta/<code>.pending. Il répond{ code, uploadId, partSize, partCount }.POST /api/transfers/uploads/:code/partsavec{ uploadId, partNumbers }renvoie des URLPUTprésignées pour ces morceaux (valables une heure, 50 au plus par appel), et les morceaux que le bucket a déjà. Chaque URL est signée avec la longueur exacte de son morceau.- Le navigateur envoie les morceaux au bucket, quatre à la fois, retente trois fois un morceau qui
échoue, et lit l’en-tête
ETagde chaque réponse. POST /api/transfers/uploads/:code/completeavec{ uploadId, parts: [{ partNumber, etag }] }assemble le fichier, vérifie sa taille contre celle annoncée, puis fait exactement ce que faitPOST /api/transfers: l’accusé, le jeton d’expéditeur,parcel.sent, et la même réponse201. Le colis ne se distingue plus d’un autre.DELETE /api/transfers/uploads/:codeavec{ uploadId }abandonne l’envoi.
Les morceaux font 8 Mio, davantage quand un fichier en demanderait plus de 10 000. Ces quatre routes
sont derrière DROP_PASSWORD, comme POST /api/transfers.
La reprise
Le navigateur garde l’envoi en cours dans localStorage, sous le nom, la taille et la date de
modification du fichier. Si la connexion tombe ou si l’onglet se ferme, redéposez le même fichier : la
page propose Reprendre l’envoi, demande au bucket quels morceaux il a déjà, et envoie le reste.
Annuler l’envoi abandonne l’envoi dans le bucket et l’oublie.
La règle CORS
Les morceaux vont du navigateur au bucket : le bucket doit autoriser PUT depuis l’adresse de votre
page, et laisser la page lire l’ETag de chaque réponse. Sans cette règle, les petits fichiers
continuent de passer, et un gros échoue avec un message qui renvoie ici.
Sur AWS S3, dans Permissions → Cross-origin resource sharing (CORS) ; sur Cloudflare R2, dans R2 → votre bucket → Settings → CORS Policy :
[
{
"AllowedOrigins": ["https://votre-livraison.vercel.app", "http://localhost:3400"],
"AllowedMethods": ["PUT"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]En ligne de commande, aws s3api put-bucket-cors --bucket <bucket> --cors-configuration file://cors.json
attend ce tableau enveloppé dans { "CORSRules": [ … ] }, et pour R2,
npx wrangler r2 bucket cors set <bucket> --file cors.json attend sa propre forme :
{
"rules": [
{
"allowed": { "origins": ["https://votre-livraison.vercel.app"], "methods": ["PUT"], "headers": ["*"] },
"exposeHeaders": ["ETag"],
"maxAgeSeconds": 3600
}
]
}colis verifier avertit quand aucune règle n’autorise PUT en exposant ETag
(Browser uploads (CORS)).
Le nettoyage
Les morceaux d’un envoi que personne n’a terminé restent stockés, et facturés, jusqu’à ce que quelque
chose les supprime. Ajoutez AbortIncompleteMultipartUpload après un jour à la règle de cycle de vie
du préfixe. R2 abandonne de lui-même les envois incomplets après sept jours, et accepte la même règle.
Sur AWS, les clés du déploiement ont besoin, en plus de s3:PutObject, s3:GetObject et
s3:DeleteObject, de s3:AbortMultipartUpload et s3:ListMultipartUploadParts pour abandonner et
reprendre un envoi.
Ce qu’il faut savoir
- La durée de vie démarre avec l’envoi. L’expiration est écrite à l’ouverture de l’envoi : un envoi lent consomme une partie de la durée choisie. L’enregistrement en attente vit un jour, ou moins si le colis expire plus tôt.
- La page et la CLI envoient en morceaux. Au-delà de 4 Mo,
colis envoyerpasse par les mêmes routes que la page, sans règle CORS (elle ne concerne que les navigateurs). Le nœud n8n envoie en une seule requête, donc sousDROP_MAX_SIZE_MB. - Tout garder en une requête : réglez
DROP_MAX_UPLOAD_MBau niveau deDROP_MAX_SIZE_MB. Plus besoin de CORS, et un fichier trop gros est refusé avant l’envoi.
Dans votre propre code
Les mêmes opérations existent dans @colis/core, pour construire un envoi direct ailleurs :
createMultipartUpload(), presignUploadPart(), listUploadedParts(),
completeMultipartUpload() et abortMultipartUpload(). Voir API.
Suivi et validation
Les quatre statuts d’un colis, la réponse du client, le jeton d’expéditeur et les routes de l’accusé de réception.
Stockages
AWS S3, Cloudflare R2, MinIO, Scaleway, Wasabi : le point d’accès est la seule différence. Les réglages de chacun pour la page de livraison, la CLI et la bibliothèque.