We work on a project with NestJS and GraphQL. In the project we consider ‘image’ module to handle all images in other modules. For serving image we use Controller:
@Get(':id')
@Header('Cache-Control', 'public, max-age=86400, s-maxage=31536000')
@Header('Content-Type', 'image/webp')
@Header('Accept-Ranges', 'bytes')
async serveImage( @Res() response: Response,
@Param('id') id: string,
@Query('w', new ParseIntPipe({ optional: true })) w?: number,
@Query('q', new ParseIntPipe({ optional: true })) q?: number, )
{
return this.imageService.serveImage({ id, width: w, quality: q, response, });
}
And for service:
async serveImage({ id, width, quality: inputQuality, response, }: ServeImageInputDto) {
try {
const MAXIMUM_WIDTH = 1920;
const quality = !isNullOrUndefined(inputQuality) && inputQuality > 0 && inputQuality <= 100 ? inputQuality : 100;
const directory = getImageDirectory(id);
const imagePath = `${directory}/${id}.webp`;
const cachePath = `${createdCachedImagesDirectory()}/${id}_${width}_${quality}.webp`;
if (!fs.existsSync(imagePath)) return null;
if (fs.existsSync(cachePath)) {
const cacheFile = fs.createReadStream(cachePath);
cacheFile.pipe(response);
} else {
const file = fs.createReadStream(imagePath);
const convertedImage = !isNullOrUndefined(width) && width > 0
? sharp({ failOnError: false })
.resize(width > MAXIMUM_WIDTH ? MAXIMUM_WIDTH : width)
.toFormat('webp', { lossless: false })
.webp({ quality, })
: sharp()
.toFormat('webp', { lossless: false })
.webp({ quality, });
file.pipe(convertedImage).pipe(response);
const cacheFile = fs.createWriteStream(cachePath);
convertedImage.pipe(cacheFile);
return new StreamableFile(convertedImage);
}
} catch (error) {
throw new InternalServerErrorException(error);
}
}
This code is ok and we do not have any problems and we can serve an image to custom size like:
https://api.*****.**/images/64eda2a390b11c507b95cd92?w=256&q=75
But for improve performance we want to implement this serving image with worker-thread (Piscina). We tried a lot but we could not succeed. We want to use piscina and sharp libraries together and image processing. Is it possible? How?