Aller au contenu
HexaTransfer
Retour au blog
Approfondissements techniques

Architecture d'upload par chunks : guide de conception

Concevez un système robuste d'upload par chunks : stratégies de découpage, uploads reprenables et optimisation du transfert parallèle.

Une architecture d'upload par chunks divise un fichier en morceaux de taille fixe ou variable et les envoie indépendamment, de sorte qu'une coupure réseau ne force pas le recommencement d'un transfert de 10 Go depuis le début. Les deux standards ouverts dominants sont AWS S3 Multipart Upload (parties de 5 Mo minimum, 10 000 parties maximum) et le protocole tus.io reprehensible (draft RFC, largement implémenté). Bien conçu, un upload par chunks délivre un débit 5 à 10 fois supérieur sur les liens à haute latence, tolère les déconnexions brèves et permet le déchiffrement parallèle côté réception. Voici comment concevoir un système qui tient réellement la charge en production.

Pourquoi les uploads monolithiques échouent à l'échelle

Un HTTP PUT unique d'un fichier de 5 Go peut échouer d'une demi-douzaine de façons. Les fenêtres de congestion TCP prennent du temps à monter, plafonnant le débit bien en dessous de la capacité du lien sur les chemins à haute latence. Les navigateurs limitent les connexions simultanées par origine à 6, laissant la majeure partie de la bande passante inutilisée. Les timeouts de requête côté serveur (nginx par défaut à 60 secondes, CloudFront à 30 secondes pour les flux non-streaming) tuent les uploads longs. Les réseaux mobiles changeant d'antenne coupent la connexion toutes les quelques minutes. Et un seul bit corrompu force le recommencement du transfert entier. Les uploads par chunks résolvent tout cela en rendant l'unité de travail petite, réessayable indépendamment et parallélisable.

Choisir la taille des chunks

La taille des chunks est un compromis. Des chunks plus petits récupèrent plus vite des échecs et offrent une granularité de progression plus fine mais ajoutent plus d'overhead HTTP. Des chunks plus grands amortissent les coûts de handshake et TLS mais gaspillent de la bande passante lorsqu'un chunk échoue et doit être retransmis. Plages typiques : 1 Mo à 5 Mo pour les uploads mobiles sur des réseaux instables, 5 Mo à 16 Mo pour les uploads web desktop, 16 Mo à 64 Mo pour les transferts serveur-à-serveur sur des liens fiables, et 100 Mo ou plus pour S3 Multipart où le plafond de 10 000 parties impose des chunks plus grands sur des fichiers de 1 To. Certains systèmes s'adaptent dynamiquement, commençant petit et augmentant à mesure que la connexion se révèle fiable.

Chunking à taille fixe versus par définition de contenu

Le chunking à taille fixe (par exemple, 8 Mo par tranche) est trivial à implémenter, favorable à la parallélisation et prend en charge des offsets de reprise exacts. Le chunking par définition de contenu, utilisé dans rsync et restic, choisit les frontières en fonction d'un hachage glissant comme le fingerprinting de Rabin, de sorte que les insertions au milieu d'un fichier ne décalent pas toutes les frontières de chunks suivantes. Le CDC est fantastique pour la déduplication dans les outils de sauvegarde mais ajoute de la complexité et des coûts CPU sans bénéfice pour le transfert pur de fichiers. Pour les architectures d'upload, le chunking à taille fixe l'emporte en simplicité et se mappe proprement sur les parties S3 multipart ou les offsets tus.io.

Protocoles d'upload reprenables

Le protocole tus.io, implémenté dans tusd (Go), tus-js-client, Uppy et de nombreux frameworks serveur, utilise HTTP PATCH avec un en-tête Upload-Offset pour ajouter des chunks. Une requête HEAD renvoie l'offset actuel sur le serveur, permettant au client de savoir où reprendre après une interruption réseau. S3 Multipart Upload utilise un modèle différent : initier l'upload pour obtenir un UploadId, uploader chaque partie (indexée à partir de 1), puis envoyer une requête CompleteMultipartUpload avec la liste des ETags. Les clients peuvent interroger ListParts pour voir ce qui a été uploadé. Les deux protocoles préservent l'état entre les redémarrages du client et survivent gracieusement aux coupures de connexion.

Concurrence d'upload parallèle

Uploader des chunks en parallèle augmente considérablement le débit sur les liens à haute latence. HTTP/1.1 est limité à 6 connexions simultanées par origine dans les navigateurs ; HTTP/2 multiplexe de nombreux flux sur une seule connexion mais reste soumis aux fenêtres de contrôle de flux. Un ordonnanceur d'upload typique met les chunks en file d'attente et en dispatche 4 à 8 en parallèle, avec contre-pression quand le serveur signale 429 ou 503. Trop de parallélisme déclenche le shaping des FAI et les limites de connexion des équipements intermédiaires ; trop peu laisse la bande passante inutilisée. Empiriquement, 4 flux parallèles sur la fibre résidentielle et 8 à 16 sur la fibre gigabit atteignent le point optimal pour la plupart des charges de travail.

État côté client et métadonnées de reprise

Les uploads reprenables requièrent que le client retienne suffisamment d'état pour reprendre après un crash de navigateur ou un arrêt d'ordinateur. IndexedDB, partie du standard Web Storage, stocke les manifestes d'upload avec le hash du fichier, le nombre de chunks et les chunks ayant réussi. Clé le manifeste par le hash SHA-256 du fichier afin que l'ajout du même fichier reprenne là où c'était arrêté. Nettoyez les manifestes obsolètes de plus de 7 jours pour éviter le gonflement. Sur mobile, WKWebView (iOS) et Chrome Custom Tabs (Android) peuvent expulser IndexedDB sous pression mémoire, donc persistez l'état critique dans le stockage natif si possible.

Gestion des chunks côté serveur

Le serveur doit réassembler les chunks en un fichier complet ou, avec S3 Multipart, déléguer la réassemblage à S3. Une architecture minimale : accepter chaque PATCH de chunk, écrire dans un blob temporaire clé par ID d'upload et index de chunk, enregistrer l'offset dans un stockage de métadonnées comme Redis ou PostgreSQL, et à CompletePart, assembler ou marquer comme complet. Utilisez le stockage d'objets (S3, Cloudflare R2, Backblaze B2) pour les blobs de chunks plutôt que le disque local, puisque les backends load-balancés ne peuvent pas partager facilement l'état local. Récupérez les uploads abandonnés après 24 à 72 heures pour libérer le stockage.

Vérification d'intégrité par chunk et de bout en bout

Vérifiez chaque chunk avec un hash à l'upload. L'ETag de S3 Multipart est un hash MD5 par partie (ou un hash composite pour l'objet complet). Pour une intégrité plus forte, calculez SHA-256 par chunk côté client et envoyez-le dans un en-tête ; le serveur le stocke avec le chunk et peut vérifier à la relecture. Après l'upload de tous les chunks, calculez une racine d'arbre de Merkle ou un hash en streaming du fichier réassemblé et renvoyez-le au client. Le client compare avec son propre hash du fichier original. Toute discordance déclenche un re-upload des chunks défaillants.

Interaction du chiffrement avec le chunking

Le chiffrement de bout en bout complique légèrement le chunking. Chaque chunk a besoin de son propre nonce pour éviter la réutilisation d'IV dans AES-GCM, et les frontières de chunks doivent faire partie du schéma d'authentification. Une approche typique : dériver une clé par chunk via HKDF-SHA256 à partir d'une clé de chiffrement de fichier racine, en utilisant l'index de chunk comme information de contexte, puis chiffrer chaque chunk avec AES-256-GCM et un nonce zéro ou incrémentiel. Inclure l'index de chunk et le nombre total de chunks dans l'AAD afin que les attaquants ne puissent pas fusionner ou réordonner des chunks. Au déchiffrement, vérifiez que tous les chunks sont présents et dans l'ordre avant de libérer le texte en clair.

Observabilité pour les systèmes par chunks

Instrumentez chaque chunk. Métriques à suivre : chunks uploadés par seconde, latence d'upload de chunk p50/p95/p99, taux de réessai par chunk et taux d'abandon d'upload. Les tableaux de bord dans Grafana ou Datadog révèlent rapidement les régressions. Les traces distribuées via OpenTelemetry lient une session client à sa gestion de chunks côté serveur. Journalisez les événements structurés en JSON afin qu'ils soient consultables dans Loki, Elasticsearch ou Splunk. Quand un client signale un upload lent, la trace montre exactement quels chunks se sont bloqués et pourquoi.

Assembler le tout

Un système d'upload par chunks prêt pour la production combine des chunks de 5 Mo à 16 Mo, tus.io ou S3 Multipart pour le protocole, 4 à 8 flux parallèles, l'état de reprise sauvegardé dans IndexedDB, les vérifications d'intégrité SHA-256 par chunk, et optionnellement du chiffrement de bout en bout par chunk avec une clé dérivée. HexaTransfer utilise le chiffrement par chunks côté client avec AES-256-GCM et les uploads reprenables pour gérer les fichiers de 10 Go de façon fiable sur des connexions instables.

Essayez-le sur https://hexatransfer.com — gratuit, sans compte, 10 Go maximum.

Envoyez vos fichiers volumineux en toute sécurité avec le chiffrement de bout en bout

Transférez des fichiers jusqu'à 10 Go gratuitement avec le chiffrement de bout en bout. Aucun compte requis. Vos fichiers sont chiffrés dans votre navigateur avant l'envoi — personne d'autre ne peut les lire.

Envoyer un fichier