2012-06-12 17 views
5

Czy istnieje skuteczniejszy sposób wyświetlania plików z zasobnika w usłudze Amazon S3 i wyodrębniania danych meta dla każdego z tych plików? Używam pakietu AWS PHP SDK.Wydajny sposób na wyodrębnianie plików i metadanych z 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 />'; 
    } 
} 

W tej chwili trzeba uruchomić get_object_list() do listy wszystkich plików, a następnie get_object_metadata() dla każdego pliku, aby uzyskać jego meta danych.

Jeśli mam 100 plików w moim segmencie, wykonuje 101 połączeń, aby uzyskać te dane. Byłoby dobrze, gdyby można było to zrobić w jednym wywołaniu.

Np:

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

Użycie obiektów s3 do przechowywania "plików" przypomina użycie całej partycji 2Gb fs do przechowywania obrazu Zork. Umieść wszystkie swoje metadane w jednym obiekcie. Tak, 100 obiektów wymaga 100 transakcji. – starbolin

Odpowiedz

1

skończyło się używając list_objects funkcję który wyciągnął lastModified meta I wymagane.

Wszystko w jednej rozmowy :)

2

wiem, że to jest nieco stary, ale napotkał ten problem i go rozwiązać I rozszerzył SDK AWS aby korzystać z funkcjonalności wsadowy dla tego typu problemu. Szybciej odzyskuje niestandardowe dane meta dla wielu plików. To jest mój kod:

/** 
    * 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

Musisz wiedzieć, że list_objects funkcja ma limitu. Nie pozwala załadować więcej niż 1000 obiektów, nawet jeśli opcja max-keys zostanie ustawiona na pewną dużą liczbę.

Do tego trzeba załadować dane kilkakrotnie naprawić:

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

W rezultacie - będziesz mieć pełną listę obiektów.


Co jeśli masz jakieś niestandardowe nagłówki? Nie zostaną one zwrócone za pośrednictwem funkcji list_objects. W takim przypadku pomoże to:

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

To jest właśnie to, czego potrzebowałem. Dzięki wielkie! – CoreDumpError

+0

@CoreDumpError serdecznie zapraszamy :) Podoba mi się ta strona internetowa, ponieważ pytania są interesujące, a odpowiedzi mogą być bardzo różne i przydatne! – Andron