Sometimes you may want to send files back to the client from the REST API. To do this with Nest, typically you need to do the following:
@Controller("file")
export class FileController {
@Get()
getFile(@Res() res: Response) {
const file = createReadStream(join(process.cwd(), "package.json"));
file.pipe(res);
}
}
But when doing this, you end up losing access to the post-controller interceptor logic. To handle this, you can return a StreamableFile instance, and behind the scenes, the framework will take care of piping the response.
Using StreamableFile
classes to process streaming files
In NestJS we can use StreamableFile
to process streaming files. To create a new StreamableFile, you can pass a Buffer or Stream to the StreamableFile constructor. Next, we create an interface in advance to return files in a specified directory to the browser. The specific code is as follows:
@Get('/model')
getFile(): StreamableFile {
const file = createReadStream(join(process.cwd(), '../../public/model.xlsx'));
return new StreamableFile(file);
}
StreamableFile
The default response header type is application/octet-stream
. The front end needs to do special processing after getting this stream. If you need to customize the response, you can use the res.set method or @Header() decorator, as shown below:
@Get()
getFile(@Res({
passthrough: true }) res: Response): StreamableFile {
const file = createReadStream(join(process.cwd(), '../../public/model.xlsx'));
res.set({
'Content-Type': 'application/json',
'Content-Disposition': 'attachment; filename="model.xlsx"',
});
return new StreamableFile(file);
}
// Or even:
@Get()
@Header('Content-Type', 'application/json')
@Header('Content-Disposition', 'attachment; filename="model.xlsx"')
getStaticFile(): StreamableFile {
const file = createReadStream(join(process.cwd(), '../../public/model.xlsx'));
return new StreamableFile(file);
}