Limiter la vitesse d’upload d’un fichier en NodeJS

En ce moment chez Wuha, nous mettons au point une application pour indexer les fichiers d’un ordinateur et les analyser dans notre moteur de recherche.

Ce programme fonctionne de la même manière que l’application de synchronisation Google Drive ou Dropbox : il surveille en temps réel les ajouts, suppressions, et modifications de fichiers sur l’ordinateur et les envoient vers le moteur de recherche Wuha pour analyse.

Dans une première version, nous instancions simplement un ReadStream du fichier. Dans le monde NodeJS, un Stream, un flux, est un objet particulier qui peut lire et/ou écrire des données. Le ReadStream permet donc de lire les données du fichier sur le disque et de les rediriger via HTTP sur notre serveur.

Le problème dans ce cas de figure est que le flux en lecture est extrêmement rapide, proche de la vitesse de lecture du disque, et va donc saturer la bande passante internet de l’utilisateur, ce qui peut aller jusqu’au blocage de sa connexion ! C’est là que les streams de type Transform entrent en jeu. Pour continuer sur l’analogie des flux, c’est un peu comme un barrage hydroélectrique sur un fleuve : un flux d’eau entre et on le transforme en électricité. Ici, des données vont entrer, on va leur appliquer des transformations et les ressortir à nouveau sous forme de flux.

Dans notre cas, ce sera un simple barrage destiné à réguler la vitesse du flux. Nous avons utilisé la librairie throttle, qui est une implémentation d’un Transform stream comptant les données entrantes et faisant des pauses régulières avec setTimeout de façon à ne pas dépasser la vitesse imposée.

Ci-dessous, un Gist illustrant le fonctionnement de ce système :

A noter que si, de base, request  / form-data  parviennent à deviner les méta-données du fichier (nom, taille…) d’un ReadStream ; ce n’est pas le cas pour un flux quelconque. C’est donc à vous de les préciser afin que tout fonctionne correctement.

Grâce à de simples manipulations de flux, nous avons donc pu contrôler la vitesse d’upload de fichiers et ainsi indexer les documents de nos utilisateurs sans pénaliser leur connexion.