Ho bisogno di cambiare alcuni metadati (Content-Type) su centinaia o migliaia di oggetti su S3. Qual è un buon modo per farlo con Ruby? Per quanto posso dire, non c'è modo di salvare solo i metadati con fog.io, l'intero oggetto deve essere nuovamente salvato. Sembra che l'utilizzo di the official sdk library richiederebbe il rolling di un ambiente wrapper solo per questa attività.Come posso aggiornare un batch di metadati di oggetti S3 usando ruby?
risposta
Hai ragione, l'SDK ufficiale ti consente di modificare i metadati dell'oggetto senza caricarlo di nuovo. Quello che fa è copy the object ma è sul server, quindi non è necessario scaricare il file e ricaricarlo.
Un wrapper sarebbe facile da implementare, qualcosa come
bucket.objects.each do |object|
object.metadata['content-type'] = 'application/json'
end
Per i lettori futuri, ecco un campionario completo di cambiare roba utilizzando Ruby AWS-sdk v1 (si veda anche questo Gist per un v2 AWS-sdk del campione):
# 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
Il tuo Gist dice che l'esempio di v2 non sembra funzionare e suggerisce che potrebbe essere un bug nell'SDK ... Prendo che non l'hai ancora risolto? – scottb
No. Basta provare il succo con l'ultima versione di v2 :) – joost
versione v2 non funziona nemmeno per me. Ho commentato la sostanza con la mia soluzione (ricaricare ogni file). –
Nel API v2, è possibile utilizzare Object#copy_from()
o Object.copy_to()
con le opzioni :metadata
e :metadata_directive => 'REPLACE'
per aggiornare i metadati di un oggetto senza scaricarlo da S3.
Il codice in Joost's gist lanci questo errore:
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.
Questo perché per default AWS ignora il :metadata
fornito con un'operazione di copia perché copia dei metadati. Dobbiamo impostare l'opzione :metadata_directive => 'REPLACE'
se vogliamo aggiornare i metadati sul posto.
Vedi http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#copy_from-instance_method
Ecco un pieno, lavorando frammento di codice che ho recentemente utilizzato per eseguire le operazioni di aggiornamento dei metadati:
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",
)
Per un facile riutilizzo:
def update_metadata(s3_object, new_metadata = {})
s3_object.copy_to(s3_object,
:metadata => new_metadata
:metadata_directive => "REPLACE"
)
end
Per aggiungere il controllo della cache, utilizzare: object.copy_to (oggetto, cache_control: "public, max-age = 333333", metadata_directive: "REPLACE") –
dopo un po 'di ricerca questo sembra funzionare per me
obj.copy_to(obj, :metadata_directive=>"REPLACE", :acl=>"public-read",:content_type=>"text/plain")
Ulteriori informazioni su questo argomento: http://groups.google.com/group/ruby-fog/browse_thread/thread/e632fc61405bf04c –
aggiunge solo i metadati con prefisso x-amz-meta-. è il modo di aggiungere solo un normale metadata Content-Type? – serengeti12