Use Piscina and Sharp libraries together for image processing in NestJS

87 views Asked by At

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?

0

There are 0 answers