colisdocs

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

  1. POST /api/transfers/uploads avec { 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 enregistrement meta/<code>.pending. Il répond { code, uploadId, partSize, partCount }.
  2. POST /api/transfers/uploads/:code/parts avec { uploadId, partNumbers } renvoie des URL PUT pré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.
  3. Le navigateur envoie les morceaux au bucket, quatre à la fois, retente trois fois un morceau qui échoue, et lit l’en-tête ETag de chaque réponse.
  4. POST /api/transfers/uploads/:code/complete avec { uploadId, parts: [{ partNumber, etag }] } assemble le fichier, vérifie sa taille contre celle annoncée, puis fait exactement ce que fait POST /api/transfers : l’accusé, le jeton d’expéditeur, parcel.sent, et la même réponse 201. Le colis ne se distingue plus d’un autre.
  5. DELETE /api/transfers/uploads/:code avec { 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 envoyer passe 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 sous DROP_MAX_SIZE_MB.
  • Tout garder en une requête : réglez DROP_MAX_UPLOAD_MB au niveau de DROP_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.

Sur cette page