1

I am trying to resize an image after streaming from google cloud storage. The streaming works fine but the resizing does not seem to work. I need to pass the image object to the resize function of sharpjs which will then resize and return the image in the API response.

My code is as below:


const express = require('express')
const {Storage} = require('@google-cloud/storage');
let server = express()
const storage = new Storage();
const bucketName = '<some-bucket-name>'

    server.get('/*', async (req, res, next) => {
      // Extract the query-parameter
      const widthString = req.query.width
      const heightString = req.query.height
      const format = req.query.format
      const fileName = req.path.substring(1);
      console.log("url: ", req.path)
      // Parse to integer if possible
      let width, height
      if (widthString) {
        width = parseInt(widthString)
      }
      if (heightString) {
        height = parseInt(heightString)
      }
      // Set the content-type of the response
      res.type(`image/${format || 'png'}`)
    
      // Get the resized image
          downloadFileStream(fileName).then((imageObj) =>{
            resize(imageObj, format, width, height).pipe(res)
          })
          .catch ((e) =>
            console.log(e)
          );
    })
    
    async function downloadFileStream(fileName){
           return await storage.bucket(bucketName).file(fileName).createReadStream().pipe()
    }

I am missing something in the way i should be calling resize after the file download. I get following error:

TypeError: Cannot read property 'on' of undefined
    at PassThrough.Readable.pipe (internal/streams/readable.js:657:8)
    at streamFile (/home/adityam/imageoptimizer/server.js:40:82)
    at /home/adityam/imageoptimizer/server.js:30:7
Aditya Mertia
  • 495
  • 7
  • 19
  • Looking at this code ... return await storage.bucket(bucketName).file(fileName).createReadStream().pipe() I'm not getting the "await" ... surely await takes a "Promise" and blocks until the promise is resolved. Looking at the docs, I'm not seeing that "pipe()" returns a Promise? Which source statement is throwing the exception? – Kolban Oct 20 '21 at 19:55
  • ```return await storage.bucket(bucketName).file(fileName).createReadStream().pipe()``` This is the line at which error is generated. In the source docs @https://github.com/googleapis/nodejs-storage/blob/HEAD/samples/streamFileDownload.js seems to take a filestream. When i skip resize() and pass resp directly then it works fine. – Aditya Mertia Oct 21 '21 at 02:30
  • I think you're missing the bucket name in your function `download File Stream` since the variable `bucketName` is used but not defined (although you have it defined globally somewhere else in your code) – Rogelio Monter Oct 22 '21 at 21:46
  • @RogelioMonter bucketName was globaly defined(I have updated the details). So this is not the issue. Issue was about how to call resize() on the file stream generated by downloadFile. – Aditya Mertia Oct 23 '21 at 03:34

1 Answers1

0

Based on this and this tutorials, I would suggest rewriting your resize function in this way:

include sharp library

const sharp =  require("sharp");

get image using downloadFileStream function, then resize

const image = downloadFileStream(fileName)
const resized = await sharp(image)
    .resize({
        width: width,
        height: height
    })
    .toBuffer()
    .then( data => {
        //...
    })

See also:

Rogelio Monter
  • 1,084
  • 7
  • 18