2012-02-14 7 views

risposta

6

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 
+0

Ulteriori informazioni su questo argomento: http://groups.google.com/group/ruby-fog/browse_thread/thread/e632fc61405bf04c –

+2

aggiunge solo i metadati con prefisso x-amz-meta-. è il modo di aggiungere solo un normale metadata Content-Type? – serengeti12

4

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 
+0

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

+0

No. Basta provare il succo con l'ultima versione di v2 :) – joost

+0

versione v2 non funziona nemmeno per me. Ho commentato la sostanza con la mia soluzione (ricaricare ogni file). –

5

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 
+0

Per aggiungere il controllo della cache, utilizzare: object.copy_to (oggetto, cache_control: "public, max-age = 333333", metadata_directive: "REPLACE") –

1

dopo un po 'di ricerca questo sembra funzionare per me

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