2008-11-06 18 views
31

J'ai téléchargé un tas d'images sur Amazon S3 et je souhaite maintenant leur ajouter un en-tête Cache-Control.Est-il possible de changer les en-têtes sur un objet S3 sans télécharger l'objet entier?

L'en-tête peut-il être mis à jour sans télécharger l'image entière? Si c'est le cas, comment?

+0

L'en-tête x-amz-metadata-directive ne fonctionne pas. Il en résulte une non-concordance de signature à chaque fois. Tous les autres en-têtes x-amz fonctionnent bien. –

Répondre

34

C'est une fonctionnalité bêta, mais vous pouvez spécifier de nouvelles méta-données lorsque vous copy an object. Spécifiez la même source et la même destination pour la copie, ce qui a pour effet de mettre à jour les métadonnées sur votre objet.

PUT /myObject HTTP/1.1 
Host: mybucket.s3.amazonaws.com 
x-amz-copy-source: /mybucket/myObject 
x-amz-metadata-directive: REPLACE 
x-amz-meta-myKey: newValue 
+6

ne pas oublier d'inclure au type de contenu de l'objet dans le paramètre en-têtes, car la demande PUT réécrit tous les en-têtes d'origine. –

+0

En général, l'opération de copie réécrit toutes les métadonnées avec les métadonnées que vous fournissez lorsque la source et la destination sont identiques. Voir [documentation] (http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectCOPY.html) pour la directive '' 'x-amz-metadata-directive''', qui nécessite des demandes de copie avec le même destination pour spécifier '' '' REPLACE'''.Si vous souhaitez conserver des métadonnées utilisateur ou S3 existantes, vous devez obtenir les métadonnées de l'objet existant, ajouter/modifier des entrées et fournir les métadonnées mises à jour dans votre demande de copie. – pauljm

10

Ceci est la version beta est disponible en faisant une commande de vente et de copier l'objet comme documented here. Il est également disponible dans leurs SDK. Par exemple, avec C#:

var s3Client = new AmazonS3Client("publicKey", "privateKey"); 
var copyRequest = new CopyObjectRequest() 
        .WithDirective(S3MetadataDirective.REPLACE) 
        .WithSourceBucket("bucketName") 
        .WithSourceKey("fileName") 
        .WithDestinationBucket("bucketName") 
        .WithDestinationKey("fileName) 
        .WithMetaData(new NameValueCollection { { "x-amz-meta-yourKey", "your-value }, { "x-amz-your-otherKey", "your-value" } }); 
var copyResponse = s3Client.CopyObject(copyRequest); 
+0

Merci pour la mise à jour. :) – Scott

+0

@Scott Salut, obtenir "Une tentative a été faite pour utiliser un objet qui n'est pas, ou n'est plus utilisable." Avec la nouvelle API –

2

avec l'amazon aws-sdk, Faire un copy_object avec les en-têtes supplémentaires semble faire l'affaire pour la mise en-têtes de contrôle de la mise en cache pour un objet S3 existant.

===================== x ======================== =======================

<?php 
    error_reporting(-1); 
    require_once 'sdk.class.php'; 

    // UPLOAD FILES TO S3 
     // Instantiate the AmazonS3 class 
    $options = array("key" => "aws-key" , "secret" => "aws-secret") ; 


     $s3 = new AmazonS3($options); 
     $bucket = "bucket.3mik.com" ; 


    $exists = $s3->if_bucket_exists($bucket); 
    if(!$exists) { 
     trigger_error("S3 bucket does not exists \n" , E_USER_ERROR); 
    } 

    $name = "cows-and-aliens.jpg" ; 
    echo " change headers for $name \n" ; 
    $source = array("bucket" => $bucket, "filename" => $name); 
    $dest = array("bucket" => $bucket, "filename" => $name); 

    //caching headers 
    $offset = 3600*24*365; 
    $expiresOn = gmdate('D, d M Y H:i:s \G\M\T', time() + $offset); 
    $headers = array('Expires' => $expiresOn, 'Cache-Control' => 'public, max-age=31536000'); 

     $meta = array('acl' => AmazonS3::ACL_PUBLIC, 'headers' => $headers); 

    $response = $s3->copy_object($source,$dest,$meta); 
    if($response->isOk()){ 
     printf("copy object done \n"); 

    }else { 
     printf("Error in copy object \n"); 
    } 

?> 

==================== === x ======================================== ==

7

Voici comment vous le faites avec AWS SDK pour PHP 2:

<?php 
require 'vendor/autoload.php'; 

use Aws\Common\Aws; 
use Aws\S3\Enum\CannedAcl; 
use Aws\S3\Exception\S3Exception; 

const MONTH = 2592000; 

// Instantiate an S3 client 
$s3 = Aws::factory('config.php')->get('s3'); 
// Settings 
$bucketName = 'example.com'; 
$objectKey = 'image.jpg'; 
$maxAge = MONTH; 
$contentType = 'image/jpeg'; 

try { 
    $o = $s3->copyObject(array(
     'Bucket' => $bucketName, 
     'Key' => $objectKey, 
     'CopySource' => $bucketName . '/'. $objectKey, 
     'MetadataDirective' => 'REPLACE', 
     'ACL' => CannedAcl::PUBLIC_READ, 
     'command.headers' => array(
      'Cache-Control' => 'public,max-age=' . $maxAge, 
      'Content-Type' => $contentType 
     ) 
    )); 

    // print_r($o->ETag); 
} catch (Exception $e) { 
    echo $objectKey . ': ' . $e->getMessage() . PHP_EOL; 
} 
?> 
+0

Cela a fonctionné pour moi avec SDK 2. Merci beaucoup. – mishka

1

En Java, essayez cette

S3Object s3Object = amazonS3Client.getObject(bucketName, fileKey); 
ObjectMetadata metadata = s3Object.getObjectMetadata(); 
Map customMetaData = new HashMap(); 
customMetaData.put("yourKey", "updateValue"); 
customMetaData.put("otherKey", "newValue"); 
metadata.setUserMetadata(customMetaData); 

amazonS3Client.putObject(new PutObjectRequest(bucketName, fileId, s3Object.getObjectContent(), metadata)); 

Vous pouvez également essayer de copier un objet. Ici, les métadonnées ne seront pas copiées lors de la copie d'un objet. Vous devez obtenir les métadonnées de l'original et configurer pour copier la demande. Cette méthode est plus recommandé d'insérer ou de métadonnées de mise à jour d'un objet Amazon S3

ObjectMetadata metadata = amazonS3Client.getObjectMetadata(bucketName, fileKey); 
ObjectMetadata metadataCopy = new ObjectMetadata(); 
metadataCopy.addUserMetadata("yourKey", "updateValue"); 
metadataCopy.addUserMetadata("otherKey", "newValue"); 
metadataCopy.addUserMetadata("existingKey", metadata.getUserMetaDataOf("existingValue")); 

CopyObjectRequest request = new CopyObjectRequest(bucketName, fileKey, bucketName, fileKey) 
     .withSourceBucketName(bucketName) 
     .withSourceKey(fileKey) 
     .withNewObjectMetadata(metadataCopy); 

amazonS3Client.copyObject(request); 
1

J'ai eu le même besoin et j'ai donc écrit pour mon environnement NodeJS.

https://github.com/newbreedofgeek/s3-bucket-cache-control

Je l'ai testé, mais pls faire preuve de diligence raisonnable d'abord comme un changement risqué.

+0

semble simple, j'ai fait tous les paramètres et essayé de courir mais obtenir ces erreurs: Cant complet .copyObject pour image.jpg, les détails de l'erreur sont: {[AccessDenied: Accès refusé] message: 'Accès refusé', Code : 'accessDenied', région: null, temps: 28 Jeu janvier 2016 10:51:24 GMT + 0530 (IST), requestId: 'XXXXXXXXXX', extendedRequestId: 'XXXXXX', statusCode: 403, réessayable: false, RetryDelay: 30} « accessDenied: Accès refusé à Request.extractError (/s3-bucket-cache-control/node_modules/aws-sdk/lib/services/s3.js:329:35) J'ai ha Avons-nous donné à l'utilisateur IAM une aide quelconque? – thekosmix

0

Voici un code d'aide en Python.

import boto 
 

 
one_year = 3600*24*365 
 
cckey = 'cache-control' 
 
s3_connection = S3Connection() 
 
bucket_name = 'my_bucket' 
 
bucket = s3_connection.get_bucket(bucket_name validate=False) 
 

 

 
for key in bucket: 
 
    key_name = key.key 
 
    if key.size == 0: # continue on directories 
 
     continue 
 
    # Get key object 
 
    key = bucket.get_key(key_name) 
 

 
    if key.cache_control is not None: 
 
     print("Exists") 
 
     continue 
 

 
    cache_time = one_year 
 
    #set metdata 
 
    key.set_metadata(name=cckey, value = ('max-age=%d, public' % (cache_time))) 
 
    key.set_metadata(name='content-type', value = key.content_type) 
 
    # Copy the same key 
 
    key2 = key.copy(key.bucket.name, key.name, key.metadata, preserve_acl=True) 
 
    continue 
 

 

Explication: Code ajoute de nouvelles métadonnées à la clé existante et copie le même fichier.

Questions connexes