Jon Snow
Jon Snow

Reputation: 11872

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!

Upvotes: 3

Views: 3610

Answers (2)

FuzzyAmi
FuzzyAmi

Reputation: 8119

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

Upvotes: 1

Jon Snow
Jon Snow

Reputation: 11872

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)

Upvotes: 1

Related Questions