s3.getObject(...).createReadStream is not a function
Asked Answered
R

3

13

I am trying to send a file from my s3 bucket to the client with my NodeJS application. This is what I have so far:

import { S3 } from '@aws-sdk/client-s3';

const BUCKET_NAME = process.env.S3_BUCKET_NAME;

const s3 = new S3({
    region: 'ap-southeast-2',
    httpOptions: {
        connectTimeout: 2 * 1000,
        timeout: 60 * 1000,
    },
});

router.get('/download/:id', async (req, res) => {
    console.log('api: GET /download/:id');
    console.log('req.params.id: ', req.params.id);
    const result = await getRequiredInfo(req.params.id);
    if (typeof result !== 'number') {
        res.attachment(result.filename);
        await s3
            .getObject({
                Bucket: BUCKET_NAME,
                Key: result.location,
            })
            .createReadStream()
            .pipe(res);
    } else {
        res.sendStatus(result);
    }
});

And when I run this code, I receive this:

(node:11224) UnhandledPromiseRejectionWarning: TypeError: s3.getObject(...).createReadStream is not a function

I wondered around on SO and looks like others are working fine with the combination of getObject and createReadStream. Is there something I am missing at this point? How should I send a file as a stream in the response?

Rhinestone answered 3/8, 2021 at 4:55 Comment(4)
github.com/aws/aws-sdk-js/issues/1436Turgite
@Turgite I don't think that one solves my Issue. For some reason the error comes up at the line with ".createReadStream()" while in that issue this function is still used.Rhinestone
I guess, s3.getObject is returning an error, that may be the reason for the error createReadStream is not a function. Add an error handler and try again.Probate
@Probate Thanks for noting that. Actually the getObject is working fine as it returns the file name, body, etc. The error only occurs after I added createReadStream(). Can you tell me how to add a handler on that one before the pipe(res)?Rhinestone
T
16

.createReadStream() is a method in aws-sdk v2. @aws-sdk/client-s3 is part of aws-sdk v3.

To get the stream from the v3 you'll need to do the following:

const response = await s3.getObject({
    Bucket: BUCKET_NAME,
    Key: key,
});

response.Body.pipe(res);

For more information about aws-sdk v3: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/

Tillis answered 3/8, 2021 at 14:6 Comment(3)
docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/…Metaphase
this is does not work for me in client-s3 v^3.121. response.Body is of type SdkStream<internal.Readable | ReadableStream<any> | Blob | undefined> | undefined. #67366881Aristotelianism
This does not work in the current SDK v3.Vaginitis
P
2

This is what worked for me

import { S3, GetObjectCommand } from "@aws-sdk/client-s3";
import { config } from 'dotenv';

// Load Environment Variable From a '.env' file
config();
const s3 = new S3( {
    region: process.env.S3_REGION,
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
});

const params = {
    Bucket: process.env.AWS_BUCKET_NAME,
    Key: key,
}
const command = new GetObjectCommand( params );
const response = await s3.send( command);

// More Logic Here

const stream = Readable.from( response.Body );
Procaine answered 16/4, 2023 at 0:32 Comment(0)
L
0

If you are using the latest version of @aws-sdk/client-s3, you may encounter the error Type 'Blob & SdkStreamMixin' is not assignable to type 'Iterable<any> | AsyncIterable<any>'.ts(2345).

To handle this, you need to perform type checking before processing the request:

const s3 = new S3({ region: process.env.AWS_REGION });
const params = {
  Bucket: process.env.AWS_BUCKET,
  Key: "transfer"
};

const command = new GetObjectCommand(params);

const response = await s3.send(command);

if (response.Body instanceof Readable) {
  const contentBuffer = Readable.from(response.Body);
  contentBuffer.pipe(process.stdout);
}

Reference: https://github.com/aws/aws-sdk-js-v3/issues/1096

Lyns answered 31/7 at 18:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.