2012-02-14 26 views
11

Tôi cần thay đổi một số siêu dữ liệu (Loại nội dung) trên hàng trăm hoặc hàng nghìn đối tượng trên S3. Cách tốt để làm điều này với ruby ​​là gì? Theo như tôi có thể nói không có cách nào để lưu chỉ siêu dữ liệu với fog.io, toàn bộ đối tượng phải được lưu lại. Có vẻ như sử dụng the official sdk library sẽ yêu cầu tôi tung ra môi trường trình bao bọc chỉ dành cho tác vụ này.Làm cách nào để cập nhật một loạt siêu dữ liệu của các đối tượng S3 bằng ruby?

Trả lời

6

Bạn nói đúng, SDK chính thức cho phép bạn sửa đổi siêu dữ liệu đối tượng mà không cần tải lên lại. Những gì nó làm là copy the object nhưng đó là trên máy chủ, do đó bạn không cần phải tải xuống tệp và tải lên lại.

Một wrapper sẽ dễ thực hiện, một cái gì đó giống như

bucket.objects.each do |object| 
    object.metadata['content-type'] = 'application/json' 
end 
+0

Thảo luận thêm về điều này tại đây: http://groups.google.com/group/ruby-fog/browse_thread/thread/e632fc61405bf04c –

+2

điều này chỉ thêm siêu dữ liệu với tiền tố x-amz-meta-. có bất kỳ cách nào để chỉ thêm siêu dữ liệu Loại nội dung thông thường không? – serengeti12

4

Đối với độc giả trong tương lai, đây là một mẫu hoàn toàn thay đổi thứ sử dụng Ruby AWS-sdk v1 (cũng thấy điều này Gist cho một v2 AWS-sdk mẫu):

# Using v1 of Ruby aws-sdk as currently v2 seems not able to do this (broken?). 
require 'aws-sdk-v1' 

key = YOUR_AWS_KEY 
secret = YOUR_AWS_SECRET 
region = YOUR_AWS_REGION 

AWS.config(access_key_id: key, secret_access_key: secret, region: region) 
s3 = AWS::S3.new 
bucket = s3.buckets[bucket_name] 
bucket.objects.with_prefix('images/').each do |obj| 
    puts obj.key 
    # Add metadata: {} to next line for more metadata. 
    obj.copy_from(obj.key, content_type: obj.content_type, cache_control: 'max-age=1576800000', acl: :public_read) 
end 
+0

Gist của bạn nói rằng mẫu v2 dường như không hoạt động, và cho thấy nó có thể là một lỗi trong SDK ... Tôi lấy nó mà bạn chưa giải quyết nó? – scottb

+0

Không. Chỉ cần thử các gist với phiên bản mới nhất của v2 :) – joost

+0

v2 phiên bản không làm việc cho tôi hoặc. Tôi đã nhận xét ý chính với giải pháp của tôi (nạp lại mỗi tệp). –

5

Trong API v2, bạn có thể sử dụng Object#copy_from() hoặc Object.copy_to() với các tùy chọn :metadata:metadata_directive => 'REPLACE' để cập nhật siêu dữ liệu của một đối tượng mà không cần tải nó từ S3.

Các mã trong Joost's gist ném lỗi này:

Aws::S3::Errors::InvalidRequest: This copy request is illegal because it is trying to copy an object to itself without changing the object's metadata, storage class, website redirect location or encryption attributes.

Đây là vì theo mặc định AWS bỏ qua :metadata cung cấp với một hoạt động sao chép vì nó sao chép siêu dữ liệu. Chúng tôi phải đặt tùy chọn :metadata_directive => 'REPLACE' nếu chúng tôi muốn cập nhật siêu dữ liệu tại chỗ.

Xem http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#copy_from-instance_method

Dưới đây là một đầy đủ, làm việc đoạn mã mà tôi sử dụng gần đây để thực hiện các hoạt động cập nhật metadata:

require 'aws-sdk' 

# S3 setup boilerplate 
client = Aws::S3::Client.new(
    :region => 'us-east-1', 
    :access_key_id => ENV['AWS_ACCESS_KEY'], 
    :secret_access_key => ENV['AWS_SECRET_KEY'], 
) 
s3 = Aws::S3::Resource.new(:client => client) 

# Get an object reference 
object = s3.bucket('my-bucket-name').object('my-object/key') 

# Create our new metadata hash. This can be any hash; in this example we update 
# existing metadata with a new key-value pair. 
new_metadata = object.metadata.merge('MY_NEW_KEY' => 'MY_NEW_VALUE') 

# Use the copy operation to replace our metadata 
object.copy_to(object, 
    :metadata => new_metadata, 

    # IMPORTANT: normally S3 copies the metadata along with the object. 
    # we must supply this directive to replace the existing metadata with 
    # the values we supply 
    :metadata_directive => "REPLACE", 
) 

Để dễ dàng tái sử dụng:

def update_metadata(s3_object, new_metadata = {}) 
    s3_object.copy_to(s3_object, 
    :metadata => new_metadata 
    :metadata_directive => "REPLACE" 
) 
end 
+0

Để thêm sử dụng bộ nhớ cache: object.copy_to (đối tượng, cache_control: 'public, max-age = 333333', metadata_directive: 'REPLACE') –

1

sau khi một số tìm kiếm điều này có vẻ phù hợp với tôi

obj.copy_to(obj, :metadata_directive=>"REPLACE", :acl=>"public-read",:content_type=>"text/plain") 
Các vấn đề liên quan