4

我正在运行一个脚本,在我的一些 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 类型。

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

4

5 回答 5

10

为了详细说明 tkotisis 响应,这是我使用 copy_to 更新内容类型所做的。您可以使用 s3object.head[:metadata] 提取现有元数据以将其复制到此处引用。

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
于 2012-11-15T14:07:03.350 回答
7

您的示例代码仅修改您的内存对象。要修改实际 S3 对象的元数据,请发出带有目标键的复制请求,即当前对象之一。

编辑

根据文档

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

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

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

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

方法

于 2012-11-15T11:29:45.143 回答
3

我正在使用 gem "aws-sdk", "~> 2" (2.2.3)

假设您有一个没有设置内容类型的当前文件(内容类型将默认设置为“二进制/八位字节流”)

如何检查内容类型文件?

如果你使用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'
)
于 2015-12-02T07:11:42.277 回答
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
于 2013-04-19T09:19:07.300 回答
1

虽然不是 Ruby,但我发现这个项目根据扩展名和重置自动猜测 mime 类型是通过其他答案所指的相同复制方法。它不是非常快,因为它必须复制 blob。如果您需要让它更快地发生,您可能可以通过 IronWorker 之类的东西来划分工作并并行复制。我为重置权限做了类似的事情

于 2013-05-13T18:48:37.793 回答