Reputation:
I'm currently generating a pre-signed url to upload an object to my AWS s3 bucket
const signedUrl = await s3.getSignedUrl('putObject', params);
Here is my params object:
const params = {
Bucket: 'mybucket',
Key: `mybucketpost-${Math.ceil(Math.random() * 10 ** 10)}.png`,
ContentType: 'image/png',
Metadata: {
ContentType: 'image/png',
},
Expires: 36000
}
I'm able to successfully generate a presigned URL and upload an object to my bucket, but when I'm trying to access the object using the s3.getSignedUrl
method, the object gets downloaded instead of the png image opening up in my browser tab. Now with all the research I've done, I understand why that's happening. That's because the system-defined object metadata Content-Type
for my object is still binary/octet-stream
.
Even though I've attempted to change the Content-Type for the object I'm generating the presigned url for to image/png
, it gets added as a user-generated metadata for the object x-amz-meta-contenttype: image/png
.
So in my AWS console, the meta-data for my uploaded object are:
System defined Cache-Control no-cache
System defined Content-Type binary/octet-stream
User defined x-amz-meta-contenttype image/png
and unfortunately, this does not solve the issue of loading up the image in the browser tab.
I've tried changing the System defined meta-data Content-Type
for an object directly through the AWS console to image/png
and as expected, the object (png) opens up in my browser tab using the object URL, but I've not been able to find a way to change System Defined meta-data Content-Type
using the AWS SDK for Node.js while generating the presigned URL using the putObject
property. Need your help with the same. Thanks!
Upvotes: 4
Views: 3571
Reputation: 306
To override System Defined Metadata, use MetadataDirective: 'REPLACE'
ContentType: 'image/png',
MetadataDirective: 'REPLACE'
Metadata: {
'custom-key': 'custom-value'
}
Upvotes: 0
Reputation: 1
For getSignedURL(...)
setting the ResponseContentType
worked for me as below:
signedUrl = await s3.getSignedUrl('putObject', params);
const params = {
Bucket: 'mybucket',
Key: `mybucketpost-${Math.ceil(Math.random() * 10 ** 10)}.png`,
ResponseContentType: 'application/binary-stream',
Expires: 36000
}
In my case I want create 2 URLS, one which will upon click download an mp4 file to disk(ResponseContentType: 'application/binary-stream') and the second will pop open a browser tab and play the video(ResponseContentType: 'video/mp4').
This works independent of what the system Content-Type value is in S3. Although if the value in S3 is set to video/mp4 you can actually leave out the ResponseContentType parameter and the default will be your S3 system content-type setting.
Upvotes: 0
Reputation: 224
I ran into the same problem when I try to set the Content-Disposition metadata whiling uploading to S3. In my case, by deleteing the Metadata
object inside params works for me.
The following is a AWS JavaScript SDK example that defines an params
object. It suggests that in order to change an System Defined metadata, you don't need to specify it in Metadata object but rather define it directly inside params
object. And anything you define inside Metadata object will become user defined.
var params = {
Bucket: 'STRING_VALUE', /* required */
Key: 'STRING_VALUE', /* required */
ACL: private | public-read | public-read-write | authenticated-read | aws-exec-read | bucket-owner-read | bucket-owner-full-control,
BucketKeyEnabled: true || false,
CacheControl: 'STRING_VALUE',
ContentDisposition: 'STRING_VALUE',
ContentEncoding: 'STRING_VALUE',
ContentLanguage: 'STRING_VALUE',
ContentType: 'STRING_VALUE',
ExpectedBucketOwner: 'STRING_VALUE',
Expires: new Date || 'Wed Dec 31 1969 16:00:00 GMT-0800 (PST)' || 123456789,
GrantFullControl: 'STRING_VALUE',
GrantRead: 'STRING_VALUE',
GrantReadACP: 'STRING_VALUE',
GrantWriteACP: 'STRING_VALUE',
Metadata: {
'<MetadataKey>': 'STRING_VALUE',
/* '<MetadataKey>': ... */
},
...
}
Upvotes: 4