Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add or modify the Content-Disposition of an existing object in Amazon S3?

We have hundreds of object in an AWS S3 bucket which don't have content disposition set.

I'm using Ruby aws-sdk gem.

How do you add or change content disposition to these objects, WITHOUT re-uploading the files again?

I have tried

obj.write(:content_disposition => 'attachment')
obj.copy_from(obj.key, :content_disposition => 'attachment')

and also copy_to(), move_to(), but none of these seem to work in adding the content disposition to the objects. In a few cases, the objects don't seem to have been modified at all (the modification time didn't change), in other cases, the object file is corrupted!


I'm aware of the alternative of using :response_content_disposition when requesting the s3 object via HTTP, which sets the Content-Disposition header,

obj.url_for(:read, :response_content_disposition => "attachment")

Thank you!

like image 577
Zack Xu Avatar asked Jan 01 '26 05:01

Zack Xu


2 Answers

We found the solution by changing the aws-sdk source code.

In s3/s3_object.rb

add the following lines to copy_from() (similar to how :content_type was handled)

if options[:content_disposition]
    copy_opts[:content_disposition] = options[:content_disposition]
    copy_opts[:metadata_directive] = "REPLACE"
end

also, in s3/client.rb

add the line marked below

object_method(:copy_object, :put,
                    :header_options => {
                    :copy_source => 'x-amz-copy-source',
                    :cache_control => 'Cache-Control',
                    :metadata_directive => 'x-amz-metadata-directive',
                    :storage_class => 'x-amz-storage-class',
                    :server_side_encryption => 'x-amz-server-side-encryption',
                    :content_type => 'Content-Type',
                    :content_disposition => 'Content-Disposition', # add this line here
                }) do

Once you've done the above, you can do the following to add content disposition to your existing object:

obj.copy_from(obj.key, :content_disposition => 'attachment', :content_type => 'image/png', :acl => :public_read)
like image 141
Zack Xu Avatar answered Jan 05 '26 05:01

Zack Xu


for future generations, here's a cli-based solution. if first lists the objects in /mybucket/brand_img/ios/ and then sets the content-disposition on each of the items to the filename. I needed this because my filenames had '@' in them and I did not want to force clients to url-encode the path.

aws s3 ls s3://mybucket/brand_img/ios/|awk {'print $4'} > objects.txt

while read line; do aws s3api copy-object --bucket mybucket  \
--copy-source /mybucket/brand_img/ios/$line --key brand_img/ios/$line \
--metadata-directive REPLACE --metadata Content-Disposition=$line --acl public-read; done < objects.txt
like image 38
FuzzyAmi Avatar answered Jan 05 '26 07:01

FuzzyAmi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!