Как обновить пакет метаданных объектов S3, используя ruby? - PullRequest
12 голосов
/ 14 февраля 2012

Мне нужно изменить некоторые метаданные (Content-Type) для сотен или тысяч объектов на S3. Какой хороший способ сделать это с рубином? Насколько я могу судить, нет способа сохранить только метаданные с fog.io , весь объект должен быть повторно сохранен. Похоже, что использование официальной библиотеки sdk потребовало бы, чтобы я развернул оболочку только для этой одной задачи.

Ответы [ 4 ]

7 голосов
/ 21 февраля 2012

Вы правы, официальный SDK позволяет вам изменять метаданные объекта, не загружая их снова. копирует объект , но он находится на сервере, поэтому вам не нужно загружать файл и повторно загружать его.

Обертку легко внедрить, что-то вроде

bucket.objects.each do |object|
  object.metadata['content-type'] = 'application/json'
end
5 голосов
/ 26 августа 2016

В v2 API вы можете использовать Object#copy_from() или Object.copy_to() с параметрами :metadata и :metadata_directive => 'REPLACE' для обновления метаданных объекта без его загрузки из S3.

Код в Суть Джуста выдает эту ошибку:

Aws :: S3 :: Errors :: InvalidRequest: этот запрос на копирование является недопустимым, поскольку он пытается скопировать объект себе без изменения объекта метаданные, класс хранения, местоположение перенаправления веб-сайта или шифрование атрибутов.

Это связано с тем, что по умолчанию AWS игнорирует :metadata, предоставленный с операцией копирования, поскольку копирует метаданные. Мы должны установить опцию :metadata_directive => 'REPLACE', если мы хотим обновить метаданные на месте.

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

Вот полный рабочий фрагмент кода, который я недавно использовал для выполнения операций обновления метаданных:

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",
)

Для легкого повторного использования:

def update_metadata(s3_object, new_metadata = {})
  s3_object.copy_to(s3_object,
    :metadata => new_metadata
    :metadata_directive => "REPLACE"
  )
end
4 голосов
/ 23 февраля 2015

Для будущих читателей, вот полный пример изменения вещей с использованием Ruby aws-sdk v1 (см. Также Gist для примера aws-sdk v2):

# 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
2 голосов
/ 11 июня 2017

после некоторого поиска мне кажется, что это работает

obj.copy_to(obj, :metadata_directive=>"REPLACE", :acl=>"public-read",:content_type=>"text/plain")
...