2008-11-06 10 views
31

He subido un montón de imágenes a Amazon S3 y ahora quiero agregar un encabezado Cache-Control para ellas.¿Es posible cambiar los encabezados en un objeto S3 sin descargar todo el objeto?

¿Se puede actualizar el encabezado sin descargar toda la imagen? ¿Si es así, cómo?

+0

el encabezado x-amz-metadata-directive no funciona. Resulta en una falta de coincidencia de la firma todo el tiempo. Todos los demás encabezados x-amz funcionan bien. –

Respuesta

34

Es la funcionalidad beta, pero puede especificar nuevos metadatos cuando copy an object. Especifique la misma fuente y destino para la copia, y esto tiene el efecto de simplemente actualizar los metadatos en su objeto.

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

no se olvide de incluir el tipo de contenido del objeto en el parámetro de encabezados, porque la solicitud PUT reescribe todos los encabezados originales. –

+0

En general, la operación de copia reescribe todos los metadatos con los metadatos que proporciona cuando el origen y el destino son los mismos. Consulte [documentación] (http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectCOPY.html) para la '' 'x-amz-metadata-directive''', que requiere solicitudes de copia con el mismo destino para especificar '' 'REPLACE'''.Si desea conservar el usuario existente o los metadatos S3, deberá obtener los metadatos del objeto existente, agregar/modificar las entradas y proporcionar los metadatos actualizados en su solicitud de copia. – pauljm

10

Esto está fuera de beta y está disponible al hacer una orden de venta y copiando el objeto como documented here. También está disponible en sus SDK. Por ejemplo con 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

Gracias por la actualización. :) – Scott

+0

@Scott hi, getting "Se intentó utilizar un objeto que no es, o ya no se puede usar." Con la nueva API –

2

con el Amazonas AWS-SDK, Hacer un copy_object con cabeceras extra parece hacer el truco para establecer cabeceras de control de caché para un objeto S3 existente.

===================== 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

ésta es la forma de hacerlo con AWS SDK para 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

Esto funcionó para mí con SDK 2. Muchas gracias. – mishka

1

En Java, pruebe este

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)); 

También puede intentar copiar el objeto. Aquí los metadatos no se copiarán mientras se copia un Objeto. Tiene que obtener los metadatos del original y configurar para copiar la solicitud. Este método es más recomendable para insertar o actualizar los metadatos de un objeto 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

que tenía la misma necesidad y por eso escribió esto para mi entorno nodejs.

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

Lo he probado, pero los pls hacer su diligencia debida en primer lugar ya que es un cambio arriesgado.

+0

parece simple, hice todas las configuraciones e intenté ejecutar pero obteniendo estos errores: No puedo completar .copyObject for image.jpg, los detalles del error son: {[AccessDenied: Acceso denegado] mensaje: 'Acceso denegado', código: 'AccessDenied', región: null, tiempo: Jue Ene 28 de el año 2016 10:51:24 GMT + 0530 (IST), RequestID: 'XXXXXXXXXX', extendedRequestId: 'XXXXXX', statusCode: 403, reintentable: falso, retryDelay: 30} 'AccessDenied: Acceso denegado en Request.extractError (/s3-bucket-cache-control/node_modules/aws-sdk/lib/services/s3.js:329:35) Yo tengo ¿Se le ha brindado al administrador un completo acceso al usuario de IAM? ¿Alguna ayuda? – thekosmix

0

Aquí hay un código de ayuda 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 
 

 

Explicación: Código añade nuevos metadatos de la clave existente y luego copias del mismo archivo.

Cuestiones relacionadas