Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating content-type after file upload on Amazon S3 with Amazon-SDK Ruby gem

Tags:

ruby

amazon-s3

I'm running a script that updates a metadata field on some of my S3 objects after they have already been uploaded to the S3 bucket. On initialization, I am setting the content-type by checking the file name.

def save_to_amazon(file, s3_object, file_name, meta_path)
  puts "uploaded #{file} to Amazon S3"
  content_type = set_content_type(file_name)
    s3_object.write(file.get_input_stream.read, :metadata => { :folders => meta_path}, :content_type => content_type)
end

At this point, the S3 content-type works fine for these objects. The problem arises when I update the metadata later on. I run something like this:

s3_object.metadata['folders'] = "some string"

At this point, I get an empty string returned when I run s3_objects.content_type after updating the metadata.

s3_object.content_type = is not available.

As far as I can tell from reading the Rdoc there isn't a way to assign content-type after uploading the S3 file. I have tried using the metadata method like

s3.object.metadata['content_type'] = "some string"
s3.object.metadata['content-type'] = "some string"

Both of these appear to assign a new custom metadata attribute instead of updating the object's mime type.

Is there a way to set this, or do I need to completely re-upload the file again?

like image 497
Paul Avatar asked Nov 29 '22 16:11

Paul


2 Answers

To elaborate on tkotisis reponse, here is what I did to update the content-type using copy_to. You can use s3object.head[:metadata] to pull out the existing metadata to copy it over as referenced here.

amazon_bucket.objects.each do |ob|
    metadata = ob.head[:metadata]
    content_type = "foo/bar"
    ob.copy_to(ob.key, :metadata => metadata, :content_type => content_type)
end

EDIT

amazon_bucket.objects.each do |ob|
    metadata = ob.metadata
    content_type = "foo/bar"
    ob.copy_to(ob.key, :metadata{:foo => metadata[:foo]}, :content_type => content_type)
end
like image 196
Paul Avatar answered Dec 06 '22 07:12

Paul


Your example code only modifies your in-memory object. To modify the metadata of the actual S3 object, issue a copy request with destination key the one of your current object.

EDIT

According to the documentation

Using the copy operation, you can rename objects by copying them and deleting the original ones.

When copying an object, you might decide to update some of the metadata values. For example, if your source object is configured to use standard storage, you might choose to use reduced redundancy storage for the object copy. You might also decide to alter some of the user-defined metadata values present on the source object. Note that if you choose to update any of the object's user configurable metadata (system or user-defined) during the copy, then you must explicitly specify all the user configurable metadata, even if you are only changing only one of the metadata values, present on the source object in your request.

I haven't tried it, but using the Ruby SDK this is probably achieved through the

- (S3Object) copy_to(target, options = {})

method.

like image 24
tkotisis Avatar answered Dec 06 '22 06:12

tkotisis