Passer au contenu

Streaming de fichiers

Il peut arriver que vous souhaitiez renvoyer un fichier depuis votre API REST au client. Pour ce faire avec Nest, vous feriez normalement ce qui suit :

Contrôleur de fichier
@Controller('file')
export class FileController {
@Get()
getFile(@Res() res: Response) {
const file = createReadStream(join(process.cwd(), 'package.json'));
file.pipe(res);
}
}

Mais ce faisant, vous finissez par perdre accès à votre logique d’intercepteur de post-contrôleur. Pour y remédier, vous pouvez retourner une instance de StreamableFile et, en arrière-plan, le framework s’occupera de pipeliner la réponse.

Classe de fichier streamable

Une classe StreamableFile est une classe qui conserve le flux qui doit être retourné. Pour créer un nouveau StreamableFile, vous pouvez passer soit un Buffer soit un Stream au constructeur de StreamableFile.

Support multiplateforme

Fastify, par défaut, peut prendre en charge l’envoi de fichiers sans avoir besoin d’appeler stream.pipe(res), donc vous n’avez pas besoin d’utiliser la classe StreamableFile. Cependant, Nest prend en charge l’utilisation de StreamableFile dans les deux types de plateformes, donc si vous finissez par passer de Express à Fastify, il n’est pas nécessaire de s’inquiéter de la compatibilité entre les deux moteurs.

Exemple

Vous pouvez trouver un exemple simple de retour de package.json en tant que fichier au lieu d’un JSON ci-dessous, mais l’idée s’étend naturellement aux images, documents et tout autre type de fichier.

Exemple de retour de fichier
import { Controller, Get, StreamableFile } from '@nestjs/common';
import { createReadStream } from 'fs';
import { join } from 'path';
@Controller('file')
export class FileController {
@Get()
getFile(): StreamableFile {
const file = createReadStream(join(process.cwd(), 'package.json'));
return new StreamableFile(file);
}
}

Le type de contenu par défaut (la valeur pour l’en-tête de réponse HTTP Content-Type) est application/octet-stream. Si vous devez personnaliser cette valeur, vous pouvez utiliser l’option type de StreamableFile, ou utiliser la méthode res.set ou le décorateur @Header(), comme ceci :

Personnalisation du Content-Type
import { Controller, Get, StreamableFile, Res } from '@nestjs/common';
import { createReadStream } from 'fs';
import { join } from 'path';
@Controller('file')
export class FileController {
@Get()
getFile(@Res() res: Response): StreamableFile {
const file = createReadStream(join(process.cwd(), 'package.json'));
res.set({
'Content-Type': 'application/json',
'Content-Disposition': 'attachment; filename="package.json"',
});
return new StreamableFile(file);
}
}