2012-06-12 19 views
5

¿Existe alguna manera más eficiente de listar archivos de un depósito en Amazon S3 y extraer también los metadatos de cada uno de esos archivos? Estoy usando AWS PHP SDK.¿Manera eficiente de extraer archivos y metadatos de Amazon S3?

if ($paths = $s3->get_object_list('my-bucket')) { 
    foreach($paths AS $path) { 
     $meta = $s3->get_object_metadata('my-bucket', $path); 
     echo $path . ' was modified on ' . $meta['LastModified'] . '<br />'; 
    } 
} 

En el momento en que se necesita para ejecutar get_object_list() para listar todos los archivos y luego get_object_metadata() para cada archivo para obtener sus metadatos.

Si tengo 100 archivos en mi depósito, hace 101 llamadas para obtener estos datos. Sería bueno si es posible hacerlo en 1 llamada.

por ejemplo:

if ($paths = $s3->get_object_list('my-bucket')) { 
    foreach($paths AS $path) { 
     echo $path['FileName'] . ' was modified on ' . $path['LastModified'] . '<br />'; 
    } 
} 
+1

Usar objetos s3 para almacenar 'archivos' es como usar una partición completa de 2Gb fs para almacenar su imagen de Zork. Pon todos tus metadatos en un objeto. Sí, 100 objetos requieren 100 transacciones. – starbolin

Respuesta

1

Terminé usando la función list_objects el que sacó el meta LastModified que requería.

Todo en una sola llamada :)

2

Sé que esto es un poco viejo, pero me encontré con este problema y resolverlo extendí la AWS SDK para utilizar la funcionalidad de lotes para este tipo de problema. Hace mucho más rápido recuperar metadatos personalizados para muchos archivos. Este es mi código:

/** 
    * Name: Steves_Amazon_S3 
    * 
    * Extends the AmazonS3 class in order to create a function to 
    * more efficiently retrieve a list of 
    * files and their custom metadata using the CFBatchRequest function. 
    * 
    * 
    */ 
    class Steves_Amazon_S3 extends AmazonS3 { 

     public function get_object_metadata_batch($bucket, $filenames, $opt = null) { 
      $batch = new CFBatchRequest(); 

      foreach ($filenames as $filename) { 

       $this->batch($batch)->get_object_headers($bucket, $filename); // Get content-type 
      } 

      $response = $this->batch($batch)->send(); 

      // Fail if any requests were unsuccessful 
      if (!$response->areOK()) { 
       return false; 
      } 
      foreach ($response as $file) { 
       $temp = array(); 
       $temp['name'] = (string) basename($file->header['_info']['url']); 
       $temp['etag'] = (string) basename($file->header['etag']); 
       $temp['size'] = $this->util->size_readable((integer) basename($file->header['content-length'])); 
       $temp['size_raw'] = basename($file->header['content-length']); 
       $temp['last_modified'] = (string) date("jS M Y H:i:s", strtotime($file->header['last-modified'])); 
       $temp['last_modified_raw'] = strtotime($file->header['last-modified']); 
       @$temp['creator_id'] = (string) $file->header['x-amz-meta-creator']; 
       @$temp['client_view'] = (string) $file->header['x-amz-meta-client-view']; 
       @$temp['user_view'] = (string) $file->header['x-amz-meta-user-view']; 

       $result[] = $temp; 
      } 

      return $result; 
     } 
    } 
2

Es necesario saber que list_objects función tiene límite. No permite cargar más de 1000 objetos, incluso si la opción max-keys se configurará en un número grande.

Para solucionar este problema es necesario cargar los datos varias veces:

private function _getBucketObjects($prefix = '', $booOneLevelOny = false) 
{ 
    $objects = array(); 
    $lastKey = null; 
    do { 
     $args = array(); 
     if (isset($lastKey)) { 
      $args['marker'] = $lastKey; 
     } 

     if (strlen($prefix)) { 
      $args['prefix'] = $prefix; 
     } 

     if($booOneLevelOny) { 
      $args['delimiter'] = '/'; 
     } 

     $res = $this->_client->list_objects($this->_bucket, $args); 
     if (!$res->isOK()) { 
      return null; 
     } 

     foreach ($res->body->Contents as $object) { 
      $objects[] = $object; 
      $lastKey = (string)$object->Key; 
     } 
     $isTruncated = (string)$res->body->IsTruncated; 
     unset($res); 
    } while ($isTruncated == 'true'); 

    return $objects; 
} 

Como resultado - usted tendrá una lista completa de los objetos.


¿Qué pasa si tiene algunos encabezados personalizados? No se devolverán a través de la función list_objects. En este caso, esto ayudará:

foreach (array_chunk($arrObjects, 1000) as $object_set) { 
    $batch = new CFBatchRequest(); 
    foreach ($object_set as $object) { 
     if(!$this->isFolder((string)$object->Key)) { 
      $this->_client->batch($batch)->get_object_headers($this->_bucket, $this->preparePath((string)$object->Key)); 
     } 
    } 

    $response = $this->_client->batch($batch)->send(); 

    if ($response->areOK()) { 
     foreach ($response as $arrHeaderInfo) { 
      $arrHeaders[] = $arrHeaderInfo->header; 
     } 
    } 
    unset($batch, $response); 
} 
+0

Esto es justo lo que necesitaba. ¡Muchas gracias! – CoreDumpError

+0

@CoreDumpError eres bienvenido :) Me gusta este sitio web porque las preguntas son interesantes y las respuestas pueden ser muy diferentes y útiles. – Andron