javascriptnode.jsamazon-web-servicesamazon-s3aws-sdk-js

Saving PDF from S3 .pipe is not a function


I'm ultimately trying to attach a file from s3 without saving it to disc, but I'm having trouble getting the file in the first place.

Here is my code:

    const s3 = require('@aws-sdk/client-s3')

    const bucketParams = {
        "Bucket": "test-upload",
        "Key": 'test.pdf'
      };
      try {
        const data = await client.send(new s3.GetObjectCommand(bucketParams));
        await new Promise((resolve, reject) => {
          data.pipe(fs.createWriteStream('example.pdf'))
            .on('error', err => reject(err))
            .on('close', () => resolve())
        })
        console.log('File saved successfully');
      } catch (err) {
        console.log(err);
      }

The error that I'm getting is:

TypeError: data.pipe is not a function

I can see that it's saving it to disc, but it's an empty file and also not formatted correctly. What am I doing wrong and how can I ultimately save this in memory to that I can attach it to an email without having to save it to disc?


Solution

  • Response from client.send for GetObjectCommand is an object with GetObjectCommandOutput type. doc ref

    Which has only metadata and Body property fields. S3 Object data is on Body field.

    So that you can fix your code with two options.

    const { Body } = await client.send(new s3.GetObjectCommand(bucketParams));
    await new Promise((resolve, reject) => {
      Body.pipe(fs.createWriteStream('example.pdf'))
        .on('error', err => reject(err))
        .on('close', () => resolve())
    })
    

    or

    const data = await client.send(new s3.GetObjectCommand(bucketParams));
    await new Promise((resolve, reject) => {
      data.Body.pipe(fs.createWriteStream('example.pdf'))
        .on('error', err => reject(err))
        .on('close', () => resolve())
    })