Reputation: 1886
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?
Upvotes: 14
Views: 24832
Reputation: 761
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
Upvotes: 1
Reputation: 93
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 );
Upvotes: 2
Reputation: 192
.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/
Upvotes: 16