Reputation: 1053
My goal is to upload a Readable
stream to S3.
The problem is that AWS api seems to accept only a ReadStream
as a stream argument.
For instance, the following snippet works just fine:
const readStream = fs.createReadStream("./file.txt") // a ReadStream
await s3.putObject({
Bucket: this.bucket,
Key: this.key,
Body: readStream,
ACL: "bucket-owner-full-control"
}
Problem starts when I try to do the same with a Readable
(ReadStream
extends stream.Readable
).
The following snippet fails
const { Readable } = require("stream")
const readable = Readable.from("data data data data") // a Readable
await s3.putObject({
Bucket: this.bucket,
Key: this.key,
Body: readable,
ACL: "bucket-owner-full-control"
}
the error I get from AWS sdk is: NotImplemented: A header you provided implies functionality that is not implemented
*** Note that I prefer a Readable
rather than a ReadStream
since I'd like to allow passing streams that are not necessarily originated from a file - an in-memory string for instance.
So a possible solution could be converting a Readable
to a Readstream
to work with the SDK.
Any help will be much appreciated!
Upvotes: 2
Views: 6792
Reputation: 1546
Example with length calculated and using Buffer:
import { Readable } from "stream";
saveCreativeImage(name: string, image: Buffer): Promise<string> {
const options: PutObjectRequest = {
ACL: 'bucket-owner-full-control',
Bucket: EnvConfig.S3_CREATIVES_BUCKET_NAME,
Key: name,
Body: Readable.from(image),
ContentType: 'image/png',
ContentLength: image.length
};
Note you used to be able to send Buffer directly but now I think a StreamingBlobTypes is required. Which is defined here: https://github.com/awslabs/smithy-typescript/blob/21ee16a06dddf813374ba88728c68d53c3674ae7/packages/types/src/streaming-payload/streaming-blob-common-types.ts#L22
I think this was changed here: https://github.com/aws/aws-sdk-js-v3/commit/96938415e65ccc4353be8f816e919215de12a1b7#diff-252b2f214c37b3c487fd068bff4968eaa1c8a6085dc9eba0d7bfe15239b05094
Upvotes: 1
Reputation: 38757
Given the Readable
is no longer a file that has metadata such as MIME type and content length you'd need to update your putObject
to include those values:
const { Readable } = require("stream")
const readable = Readable.from("data data data data") // a Readable
await s3.putObject({
Bucket: this.bucket,
Key: this.key,
Body: readable,
ACL: "bucket-owner-full-control",
ContentType: "text/plain",
ContentLength: 42 // calculate length of buffer
}
Hopefully that helps!
Upvotes: 4