Home > database >  Can't pipe object from S3 in node.js
Can't pipe object from S3 in node.js

Time:11-12

I'm trying to get a file from AWS S3 and pipe it to the Express response.

My current code:

  async getMedia(key) {
    const data = await s3.getObject(
      {
        Bucket: process.env.AWS_BUCKET_NAME,
        Key: key,
      },
      (err, data) => {
        if (err) {
          throw err;
        } else data;
      }
    );
    return data;
  }
router.get('/:path/:key', async (req, res, next) => {
  try {
    const key = req.params.key;
    const path = req.params.path;
    fileService.getMedia(`${path}/${key}`).createReadStream().pipe(res);
  } catch (error) {
    next(error);
  }
});

It is throwing this error: TypeError: fileService.getMedia(...).createReadStream is not a function

I've already tried piping data.Body, data.body, but both were undefined. Can somebody tell me what's the problem right here?

CodePudding user response:

don't know about AWS S3, but the following syntax is strange:

const data = await s3.getObject(
  ...,
  (err, data) => {
    if (err) {
      throw err;
    } else data; // you're missing a return here, aren't you ?
  }
);

return data;

You're passing a callback with your (err, data) => {} function, which is a way to work without promises. In the same time, you're using async/await which is a way to work with promises : you should pick one.

Considering the callbacks are your way, your code could become :

getMedia(key, callback) {
  s3.getObject(
    {
      Bucket: process.env.AWS_BUCKET_NAME,
      Key: key,
    },
    callback,
  );
}
router.get('/:path/:key', (req, res, next) => {
  const key = req.params.key;
  const path = req.params.path;
  fileService.getMedia(
    `${path}/${key}`,
    (err, data) => {
      if (err) {
        next(err);
      } else {
        data.createReadStream().pipe(res);
      }
    }
 );
});

Considering the promises are your way, the code could be (indeed awaiting for getMedia) :

async getMedia(key) {
  const data = await s3.getObject(
    {
      Bucket: process.env.AWS_BUCKET_NAME,
      Key: key,
    }
  );

  return data;
}
router.get('/:path/:key', async (req, res, next) => {
  try {
    const key = req.params.key;
    const path = req.params.path;

    const media = await fileService.getMedia(`${path}/${key}`);

    media.createReadStream().pipe(res);
  } catch (error) {
    next(error);
  }
});

CodePudding user response:

Thanks to @LawrenceCherone, forgot to add await for fileService.getMedia

  • Related