使用Amazon-SDK Ruby gem在Amazon S3上上传文件后更新内容类型

时间:2012-11-15 09:56:28

标签: ruby amazon-s3

我正在运行一个脚本,在已经上传到S3存储桶后,会更新某些S3对象上的元数据字段。在初始化时,我通过检查文件名来设置内容类型。

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

此时,S3内容类型适用于这些对象。我稍后更新元数据时会出现问题。我运行这样的事情:

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

此时,我在更新元数据后运行s3_objects.content_type时返回一个空字符串。

s3_object.content_type =不可用。

据我所知,在阅读Rdoc时,上传S3文件后无法分配内容类型。我尝试使用像

这样的元数据方法
s3.object.metadata['content_type'] = "some string"
s3.object.metadata['content-type'] = "some string"

这两个似乎都分配了一个新的自定义元数据属性,而不是更新对象的mime类型。

有没有办法设置,或者我是否需要再次完全重新上传文件?

5 个答案:

答案 0 :(得分:8)

详细说明tkotisis响应,这是我使用copy_to更新内容类型的方法。您可以使用s3object.head [:metadata]提取现有元数据,将其复制为引用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

修改

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

答案 1 :(得分:6)

您的示例代码仅修改您的内存中对象。 要修改实际S3对象的元数据,请发出一个复制请求,其目标键是当前对象的一个​​。

修改

根据documentation

  

使用复制操作,您可以通过复制和重命名对象   删除原始的。

     

复制对象时,您可能决定更新一些对象   元数据值。例如,如果源对象配置为   使用标准存储,您可以选择使用减少冗余   存储对象副本。你也可能决定改变一些   源对象上存在的用户定义的元数据值。注意   如果您选择更新任何对象的用户可配置   复制期间的元数据(系统或用户定义),然后您必须   显式指定所有用户可配置的元数据,即使您是   仅更改源上存在的一个元数据值   请求中的对象。

我没有尝试过,但使用Ruby SDK可能是通过

实现的
- (S3Object) copy_to(target, options = {})

method

答案 2 :(得分:2)

确保将ACL设置为:public read,否则复制后文件将不可用。

这对我有用:

bucket.objects.with_prefix('my_assets').each do |obj|
  metadata = obj.head[:metadata]
  content_type = "application/pdf"
  obj.copy_to(obj.key, :metadata => metadata, :content_type => content_type)
  obj.acl = :public_read
end

答案 3 :(得分:2)

我正在使用宝石“aws-sdk”,“〜> 2”(2.2.3)

假设您有一个没有设置内容类型的当前文件(默认情况下,Content-type将被设置为“binary / octet-stream”)

如何检查内容类型文件?

如果您使用 RestClient ,如下所示:

对象意味着Aws :: S3 :: Object

bucket = Aws::S3::Bucket.new(bucket_name)
object = bucket.object(key)

RestClient.head(object.presigned_url(:head)) do |resp|
  puts resp.headers
  puts resp.headers[:content_type]
end

如何更改内容类型文件?

在我的情况下,我想将内容类型更改为'image / jpeg',当前对象是'binary / octet-stream',这样你就可以

object.copy_from(
  object, 
  content_type: 'image/jpeg', 
  metadata_directive: 'REPLACE'
)

答案 4 :(得分:1)

虽然不是Ruby我发现this project根据扩展名自动猜测mime类型,并且重置是通过与其他答案所引用的相同的复制方法。它不是非常快,因为它必须复制blob。如果你需要让它更快地发生,你可能会分割工作并通过IronWorker之类的东西并行复制。我做了similar thing for resetting permissions