Comment diffuser des fichiers volumineux avec des flux Node.js dans NestJS
Apprenez à gérer des fichiers volumineux de manière efficace et fiable sur un serveur NestJS avec les flux Node.js, les compartiments S3 et CSV vers JSON.
Dans cet article, nous allons apprendre à gérer des fichiers volumineux sur un Pas serveur efficacement. En utilisant Flux Node.jsnous nous occuperons des téléchargements, des téléchargements sur le disque et Compartiments S3 et même le traitement de fichiers avec un exemple CSV vers JSON. Après avoir lu cet article, vous n’aurez plus à vous soucier du crash de votre serveur à cause de fichiers volumineux.
Conditions préalables
Pour suivre et tirer le meilleur parti de cet article, vous aurez besoin de connaissances de base sur le fonctionnement général des téléchargements HTTP et d’une certaine familiarité avec Papillon de nuit pour la gestion des téléchargements, une connaissance de base du SDK AWS S3 et une compréhension de base de l’architecture NestJS.
Configuration du projet
Commençons par créer un projet NestJS :
nest new stream-app
cd stream-app
Ensuite, exécutez la commande ci-dessous pour créer le FilesModule, FilesController, FilesService et CSVController fichiers :
nest g module files \
&& nest g controller files \
&& nest g service files \
&& nest g controller files/csv \
&& nest g service files/csv \
&& nest g controller files/s3 \
&& nest g service files/s3
Installez les dépendances dont nous aurons besoin pour ce projet :
Ici, nous utiliserons multer pour gérer les téléchargements, csv-parser pour transformer CSV en JSON, mime-types pour définir le type de contenu correct pour les fichiers, @aws-sdk/client-s3 pour télécharger des fichiers sur un service de stockage compatible S3 (DigitalOcean Spaces) et @nestjs/config pour récupérer les variables d’environnement.
Ensuite, pour utiliser le service NestJS Config dans notre application, nous devons importer le ConfigModule. Mettez à jour votre app.module.ts fichier avec les éléments suivants :
Enfin, dans le répertoire racine, créez un dossier appelé storage et ajoutez-y un fichier volumineux (au moins 100 Mo pour montrer les avantages du streaming en termes de mémoire).
Par exemple:
stream - app / storage / large - report.pdf;
Streaming de base dans NestJS
Maintenant, la mauvaise façon d’envoyer un fichier volumineux à un utilisateur est d’utiliser readFileSync(). Cela charge l’intégralité du fichier en mémoire et l’envoie en une seule fois. Cette approche n’est pas pratique pour les fichiers volumineux ou les applications à grande échelle.
Heureusement, Node.js nous permet de travailler avec des flux. Les flux sont un moyen de gérer les données de manière efficace, progressive et non bloquante. De cette façon, les données sont traitées par morceaux plutôt que dans leur ensemble. En utilisant createReadStream()nous lisons un fichier par morceaux de 64 Ko (par défaut).
Mettez à jour votre files.controller.ts fichier avec les éléments suivants :
Dans le code ci-dessus, le @Res({ passthrough: true }) decorator dit à NestJS de nous permettre de définir les en-têtes (modifier la réponse) tout en gérant le renvoi des données de réponse (ce qui signifie que nous n’avons pas besoin d’appeler res.send()).
Les en-têtes que nous définissons sont :
Content-Type: Qui indique au navigateur le type de fichier que nous envoyons
Content-Disposition: Qui indique au navigateur comment nommer le fichier et télécharger le fichier
StreamableFile(fileStream) encapsule le flux brut, permettant à NestJS de comprendre comment le renvoyer en réponse. Cette approche fonctionne à la fois pour Express et Fastify. Le StreamableFile classe gère les différences de bas niveau, donc si vous souhaitez passer à Fastify, il vous suffit de modifier votre main.ts fichier et installez l’adaptateur.
Téléchargement de fichiers amélioré
L’exemple précédent fonctionne, mais en production, nous souhaiterons plus de choses comme une meilleure gestion des erreurs, une validation des entrées, des en-têtes correctement définis et une logique réutilisable.
Mettez à jour votre files.service.ts fichier avec les éléments suivants :
Dans le code ci-dessus, nous effectuons d’abord une validation de base du nom de fichier pour empêcher les valeurs nulles ou non définies de provoquer des plantages. Ensuite, nous améliorons la sécurité en empêchant les attaques par traversée de répertoire (nous bloquons les tentatives d’accès aux fichiers en dehors du répertoire de stockage). Enfin, nous implémentons une gestion appropriée des erreurs à l’aide des exceptions de NestJS.
Veuillez noter que existsSync() vérifie si un chemin ou un répertoire spécifié existe ; il renvoie vrai si c’est le cas et faux si ce n’est pas le cas.
Maintenant, mettez à jour votre *files.controller.ts* pour inclure le point de terminaison suivant :
Dans le code ci-dessus, nous implémentons d’abord la sélection dynamique de fichiers à l’aide d’un paramètre de requête name. Nous transmettons ensuite ce nom à notre getFileStream(name) méthode pour obtenir le flux et le chemin. En utilisant statSync()nous obtenons la taille du fichier, que nous définirons dans les en-têtes pour aider les navigateurs à afficher des barres de progression pendant le téléchargement. Nous obtenons l’extension du fichier et utilisons la bibliothèque de types MIME pour la mapper au type MIME précis, par exemple : application/pdf ou image/jpeg. Enfin, nous définissons les en-têtes avant de permettre à NestJS de gérer la réponse.
Lorsque nous téléchargeons des fichiers, les navigateurs mettent parfois en cache la réponse, ce qui peut entraîner des problèmes tels que l’obtention de versions obsolètes des fichiers par les utilisateurs. En définissant Cache-Controlnous évitons de tels problèmes.
Téléchargement de fichiers volumineux
Voyons ensuite comment gérer les téléchargements avec des flux. Nous passerons en revue les téléchargements en streaming sur le disque et les téléchargements en streaming vers les compartiments S3.
Téléchargement sur le disque
Ajoutez le Post/upload itinéraire ci-dessous vers le FilesController :
Dans le code ci-dessus, @UseInterceptors est un décorateur NestJS qui nous permet d’attacher des intercepteurs à un gestionnaire de route. Nous attachons ici FileInterceptorqui est un assistant NestJS qui encapsule Multer, nous aide à récupérer le fichier de la requête, à l’analyser avec Multer et à le rendre disponible dans notre contrôleur avec le @UploadedFile() décorateur.
FileInterceptor prend le nom du champ dans les données du formulaire qui contient notre fichier (file) et l’objet de configuration Multer. Nous définissons storage à diskStorage au lieu de mettre le fichier en mémoire tampon. De cette façon, nous écrivons le fichier morceau par morceau au fur et à mesure de sa réception.
Le diskStorage() la méthode prend le destination (le répertoire dans lequel nous voulons enregistrer le fichier) et filenamequi est une fonction utilisée pour déterminer le nom du fichier.
Enfin, avec le @UploadedFile() décorateur, nous avons accès à l’objet fichier, qui contient des informations telles que le filename, originalname, mimetype, size, path et buffer. Mais comme nous définissons le stockage sur diskStorage, file.buffer serait undefined. En utilisant le file objet, nous renvoyons quelques détails en réponse pour montrer que le téléchargement a réussi.
Téléchargement vers S3
Ici, nous allons d’abord télécharger le fichier en utilisant diskStorage()puis diffusez-le directement dans notre compartiment S3.
Dans cet exemple, nous utiliserons DigitalOcean Spaces, qui est entièrement compatible S3. Il utilise le SDK AWS de la même manière, mais avec un point de terminaison personnalisé et une URL CDN de DigitalOcean.
Mettez à jour votre s3.service.ts fichier avec les éléments suivants :
Dans notre uploadImageStream() méthode, nous définissons d’abord une clé unique pour le fichier ou l’objet, puis nous configurons la commande de téléchargement AWS SDK v3, en transmettant le flux lisible comme corps et en définissant le ContentLength.
Enfin, nous effectuons le téléchargement dans notre try-catch bloquer et renvoyer le path et key.
Ensuite, mettez à jour votre s3.controller.ts déposer avec ce qui suit ;
Dans notre uploadToS3 gestionnaire de route, nous passons le location et file au uploadImageStream() méthode et renvoie une réponse de succès avec le key et path. Si une erreur se produit, nous la renvoyons. Enfin, nous effaçons le fichier temporairement stocké de notre disque en utilisant fs.unlinkSync(file.path).
Traitement de fichiers volumineux : exemple CSV-JSON
Mettez à jour votre csv.service.ts fichier avec les éléments suivants :
Dans le processCsvStream() méthode, nous créons d’abord une nouvelle promesse pour gérer la nature asynchrone du streaming. Le tableau résultant est l’endroit où chaque ligne analysée du CSV sera stockée au fur et à mesure de son arrivée (pour les fichiers plus volumineux, remplacez-la par la logique de la base de données). Ensuite, nous créons un flux CSV en utilisant csv() depuis csv-parserqui fonctionne comme un flux de transformation. Un flux de transformation est un flux capable de lire et d’écrire des données (nous lisons des données CSV brutes et les écrivons en JSON, une ligne à la fois).
fileStream.pipe(csvStream) envoie des morceaux de données CSV brutes dans le csv-parser. Lorsque les données sont dans le csv-parseril le convertit en JSON ligne par ligne. Une fois le csv-parser a converti une ligne en objet JSON, il émet cet objet JSON en tant qu’événement de données. Cet événement de données est ensuite géré par notre gestionnaire d’événements, qui prend chaque objet JSON résultant et le pousse dans notre results tableau.
Nous avons deux autres gestionnaires d’événements pour error et end. Quand un error l’événement est reçu, nous rejetons la promesse avec une exception de mauvaise demande. Quand le end L’événement est reçu, cela signifie que l’intégralité du fichier CSV a été traité, et nous résolvons ensuite la promesse avec les résultats collectés.
Maintenant, mettez à jour votre csv.controller.ts fichier avec les éléments suivants :
Dans cet article, nous avons expliqué comment gérer les téléchargements de fichiers, les téléchargements sur le disque et S3 ainsi que le traitement des fichiers. Vous savez désormais quoi faire, quoi ne pas faire et les raisons. Les prochaines étapes possibles consistent à ajouter une logique de base de données à l’exemple CSV vers JSON ou à ajouter une logique de nouvelle tentative pour les téléchargements S3.
octobre 15, 2025
Comment diffuser des fichiers volumineux avec des flux Node.js dans NestJS
Apprenez à gérer des fichiers volumineux de manière efficace et fiable sur un serveur NestJS avec les flux Node.js, les compartiments S3 et CSV vers JSON.
Dans cet article, nous allons apprendre à gérer des fichiers volumineux sur un Pas serveur efficacement. En utilisant Flux Node.jsnous nous occuperons des téléchargements, des téléchargements sur le disque et Compartiments S3 et même le traitement de fichiers avec un exemple CSV vers JSON. Après avoir lu cet article, vous n’aurez plus à vous soucier du crash de votre serveur à cause de fichiers volumineux.
Conditions préalables
Pour suivre et tirer le meilleur parti de cet article, vous aurez besoin de connaissances de base sur le fonctionnement général des téléchargements HTTP et d’une certaine familiarité avec Papillon de nuit pour la gestion des téléchargements, une connaissance de base du SDK AWS S3 et une compréhension de base de l’architecture NestJS.
Configuration du projet
Commençons par créer un projet NestJS :
Ensuite, exécutez la commande ci-dessous pour créer le FilesModule,
FilesController
,FilesService
etCSVController
fichiers :Installez les dépendances dont nous aurons besoin pour ce projet :
Ici, nous utiliserons
multer
pour gérer les téléchargements,csv-parser
pour transformer CSV en JSON,mime-types
pour définir le type de contenu correct pour les fichiers,@aws-sdk/client-s3
pour télécharger des fichiers sur un service de stockage compatible S3 (DigitalOcean Spaces) et@nestjs/config
pour récupérer les variables d’environnement.Ensuite, pour utiliser le service NestJS Config dans notre application, nous devons importer le
ConfigModule
. Mettez à jour votreapp.module.ts
fichier avec les éléments suivants :Enfin, dans le répertoire racine, créez un dossier appelé
storage
et ajoutez-y un fichier volumineux (au moins 100 Mo pour montrer les avantages du streaming en termes de mémoire).Par exemple:
Streaming de base dans NestJS
Maintenant, la mauvaise façon d’envoyer un fichier volumineux à un utilisateur est d’utiliser
readFileSync()
. Cela charge l’intégralité du fichier en mémoire et l’envoie en une seule fois. Cette approche n’est pas pratique pour les fichiers volumineux ou les applications à grande échelle.Heureusement, Node.js nous permet de travailler avec des flux. Les flux sont un moyen de gérer les données de manière efficace, progressive et non bloquante. De cette façon, les données sont traitées par morceaux plutôt que dans leur ensemble. En utilisant
createReadStream()
nous lisons un fichier par morceaux de 64 Ko (par défaut).Mettez à jour votre
files.controller.ts
fichier avec les éléments suivants :Dans le code ci-dessus, le
@Res({ passthrough: true })
decorator dit à NestJS de nous permettre de définir les en-têtes (modifier la réponse) tout en gérant le renvoi des données de réponse (ce qui signifie que nous n’avons pas besoin d’appelerres.send()
).Les en-têtes que nous définissons sont :
Content-Type
: Qui indique au navigateur le type de fichier que nous envoyonsContent-Disposition
: Qui indique au navigateur comment nommer le fichier et télécharger le fichierStreamableFile(fileStream)
encapsule le flux brut, permettant à NestJS de comprendre comment le renvoyer en réponse. Cette approche fonctionne à la fois pour Express et Fastify. LeStreamableFile
classe gère les différences de bas niveau, donc si vous souhaitez passer à Fastify, il vous suffit de modifier votremain.ts
fichier et installez l’adaptateur.Téléchargement de fichiers amélioré
L’exemple précédent fonctionne, mais en production, nous souhaiterons plus de choses comme une meilleure gestion des erreurs, une validation des entrées, des en-têtes correctement définis et une logique réutilisable.
Mettez à jour votre
files.service.ts
fichier avec les éléments suivants :Dans le code ci-dessus, nous effectuons d’abord une validation de base du nom de fichier pour empêcher les valeurs nulles ou non définies de provoquer des plantages. Ensuite, nous améliorons la sécurité en empêchant les attaques par traversée de répertoire (nous bloquons les tentatives d’accès aux fichiers en dehors du répertoire de stockage). Enfin, nous implémentons une gestion appropriée des erreurs à l’aide des exceptions de NestJS.
Maintenant, mettez à jour votre
*files.controller.ts*
pour inclure le point de terminaison suivant :Dans le code ci-dessus, nous implémentons d’abord la sélection dynamique de fichiers à l’aide d’un paramètre de requête
name
. Nous transmettons ensuite ce nom à notregetFileStream(name)
méthode pour obtenir le flux et le chemin. En utilisantstatSync()
nous obtenons la taille du fichier, que nous définirons dans les en-têtes pour aider les navigateurs à afficher des barres de progression pendant le téléchargement. Nous obtenons l’extension du fichier et utilisons la bibliothèque de types MIME pour la mapper au type MIME précis, par exemple :application/pdf
ouimage/jpeg
. Enfin, nous définissons les en-têtes avant de permettre à NestJS de gérer la réponse.Téléchargement de fichiers volumineux
Voyons ensuite comment gérer les téléchargements avec des flux. Nous passerons en revue les téléchargements en streaming sur le disque et les téléchargements en streaming vers les compartiments S3.
Téléchargement sur le disque
Ajoutez le
Post/upload
itinéraire ci-dessous vers le FilesController :Dans le code ci-dessus,
@UseInterceptors
est un décorateur NestJS qui nous permet d’attacher des intercepteurs à un gestionnaire de route. Nous attachons iciFileInterceptor
qui est un assistant NestJS qui encapsule Multer, nous aide à récupérer le fichier de la requête, à l’analyser avec Multer et à le rendre disponible dans notre contrôleur avec le@UploadedFile()
décorateur.FileInterceptor
prend le nom du champ dans les données du formulaire qui contient notre fichier (file
) et l’objet de configuration Multer. Nous définissonsstorage
àdiskStorage
au lieu de mettre le fichier en mémoire tampon. De cette façon, nous écrivons le fichier morceau par morceau au fur et à mesure de sa réception.Le
diskStorage()
la méthode prend ledestination
(le répertoire dans lequel nous voulons enregistrer le fichier) etfilename
qui est une fonction utilisée pour déterminer le nom du fichier.Enfin, avec le
@UploadedFile()
décorateur, nous avons accès à l’objet fichier, qui contient des informations telles que lefilename
,originalname
,mimetype
,size
,path
etbuffer
. Mais comme nous définissons le stockage surdiskStorage
,file.buffer
seraitundefined
. En utilisant lefile
objet, nous renvoyons quelques détails en réponse pour montrer que le téléchargement a réussi.Téléchargement vers S3
Ici, nous allons d’abord télécharger le fichier en utilisant
diskStorage()
puis diffusez-le directement dans notre compartiment S3.Mettez à jour votre
s3.service.ts
fichier avec les éléments suivants :Dans notre
uploadImageStream()
méthode, nous définissons d’abord une clé unique pour le fichier ou l’objet, puis nous configurons la commande de téléchargement AWS SDK v3, en transmettant le flux lisible comme corps et en définissant leContentLength
.Enfin, nous effectuons le téléchargement dans notre
try-catch
bloquer et renvoyer lepath
etkey
.Ensuite, mettez à jour votre
s3.controller.ts
déposer avec ce qui suit ;Dans notre
uploadToS3
gestionnaire de route, nous passons lelocation
etfile
auuploadImageStream()
méthode et renvoie une réponse de succès avec lekey
etpath
. Si une erreur se produit, nous la renvoyons. Enfin, nous effaçons le fichier temporairement stocké de notre disque en utilisantfs.unlinkSync(file.path)
.Traitement de fichiers volumineux : exemple CSV-JSON
Mettez à jour votre
csv.service.ts
fichier avec les éléments suivants :Dans le
processCsvStream()
méthode, nous créons d’abord une nouvelle promesse pour gérer la nature asynchrone du streaming. Le tableau résultant est l’endroit où chaque ligne analysée du CSV sera stockée au fur et à mesure de son arrivée (pour les fichiers plus volumineux, remplacez-la par la logique de la base de données). Ensuite, nous créons un flux CSV en utilisantcsv()
depuiscsv-parser
qui fonctionne comme un flux de transformation. Un flux de transformation est un flux capable de lire et d’écrire des données (nous lisons des données CSV brutes et les écrivons en JSON, une ligne à la fois).fileStream.pipe(csvStream)
envoie des morceaux de données CSV brutes dans lecsv-parser
. Lorsque les données sont dans lecsv-parser
il le convertit en JSON ligne par ligne. Une fois lecsv-parser
a converti une ligne en objet JSON, il émet cet objet JSON en tant qu’événement de données. Cet événement de données est ensuite géré par notre gestionnaire d’événements, qui prend chaque objet JSON résultant et le pousse dans notreresults
tableau.Nous avons deux autres gestionnaires d’événements pour
error
etend
. Quand unerror
l’événement est reçu, nous rejetons la promesse avec une exception de mauvaise demande. Quand leend
L’événement est reçu, cela signifie que l’intégralité du fichier CSV a été traité, et nous résolvons ensuite la promesse avec les résultats collectés.Maintenant, mettez à jour votre
csv.controller.ts
fichier avec les éléments suivants :Enfin, vérifiez votre
files.module.ts
et vérifiez que tous les fournisseurs et contrôleurs sont correctement configurés, comme indiqué ci-dessous :Conclusion
Dans cet article, nous avons expliqué comment gérer les téléchargements de fichiers, les téléchargements sur le disque et S3 ainsi que le traitement des fichiers. Vous savez désormais quoi faire, quoi ne pas faire et les raisons. Les prochaines étapes possibles consistent à ajouter une logique de base de données à l’exemple CSV vers JSON ou à ajouter une logique de nouvelle tentative pour les téléchargements S3.
Source link
Partager :
Articles similaires