2012-10-12 143 views
8

Estoy usando el código mencionado a continuación para obtener una lista de todos los nombres de archivos de s3 bucket. Tengo dos cubos en s3. Para uno de los códigos debajo del depósito, se devuelven todos los nombres de los archivos (más de 1000), pero el mismo código devuelve solo 1000 nombres de archivo para otro depósito. Simplemente no entiendo lo que está pasando. ¿Por qué el mismo código se ejecuta para un depósito y no para otro?Amazon s3 devuelve solo 1000 entradas para una categoría y todas para otra categoría (usando Java SDK)?

También mi cubo tiene estructura de jerarquía folder/filename.jpg.

ObjectListing objects = s3.listObjects("bucket.new.test"); 
       do { 

        for (S3ObjectSummary objectSummary : objects.getObjectSummaries()) { 
         String key = objectSummary.getKey(); 
         System.out.println(key); 


        } 
        objects = s3.listNextBatchOfObjects(objects); 
       } while (objects.isTruncated()); 

Respuesta

4

Mejorar en la propia respuesta de @ Abhishek. Este código es un poco más corto. También corrigió nombres de variables.

List<S3ObjectSummary> keyList = new ArrayList<S3ObjectSummary>(); 
ObjectListing objects = s3.listObjects("bucket.new.test"); 
keyList.addAll(objects.getObjectSummaries()); 

while (objects.isTruncated()) { 
    objects = s3.listNextBatchOfObjects(objects); 
    keyList.addAll(objects.getObjectSummaries()); 
} 
+0

Pero, ¿cuál es la causa raíz? ¿Por qué el mismo código había funcionado para un caso y no para otro? – morsik

+0

Esa es una buena pregunta para la que no tengo la respuesta. Solo tomé el código de @ Abhishek y lo "arreglé". Mi única conjetura es que es una propiedad del cubo. – oferei

+1

Tengo el mismo problema con la versión "vieja" de la API Java s3. Amazon presentó "v2", que debería resolver el problema: http://docs.aws.amazon.com/AmazonS3/latest/dev/ListingObjectKeysUsingJava.html Nota, utiliza 's3client.listObjectsV2' y' req.setContinuationToken (result.getNextContinuationToken()) '. El último debe realizar llamadas REST GET subyacentes por separado a s3 (como single get, devuelve hasta 1000 claves por defecto, http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html) – morsik

4

acabo de cambiar por encima de código para utilizar addAll en lugar de utilizar para bucle para añadir objetos de uno en uno y ha funcionado para mí. cambios en el código son como:

 List<S3ObjectSummary> keyList = new ArrayList<S3ObjectSummary>(); 
     ObjectListing object = s3.listObjects("bucket.new.test"); 
     keyList = object.getObjectSummaries(); 
     object = s3.listNextBatchOfObjects(object); 

     while (object.isTruncated()){ 
      keyList.addAll(current.getObjectSummaries()); 
      object = s3.listNextBatchOfObjects(current); 
     } 
     keyList.addAll(object.getObjectSummaries()); 

Después de que simplemente puede utilizar cualquier iterater sobre la lista keyList.

+0

Sugiero usar keyList.addAll (x) en lugar de asignar a keyList. De esta forma, no está modificando un miembro privado de ObjectListing (que fue devuelto por getObjectSummaries) más tarde usando addAll. Y, como ya asignó una lista en la primera línea, ya está todo listo. – oferei

1

Si desea obtener todos los objetos (más de 1000 claves), debe enviar otro paquete con la última clave para S3. Aquí está el código.

private static String lastKey = ""; 
private static String preLastKey = ""; 
... 

do{ 
     preLastKey = lastKey; 
     AmazonS3 s3 = new AmazonS3Client(new ClasspathPropertiesFileCredentialsProvider()); 

     String bucketName = "bucketname";   

     ListObjectsRequest lstRQ = new ListObjectsRequest().withBucketName(bucketName).withPrefix(""); 

     lstRQ.setMarker(lastKey); 

     ObjectListing objectListing = s3.listObjects(lstRQ); 

     // loop and get file on S3 
     for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) { 
      // get oject and do something..... 
     } 
}while(lastKey != preLastKey); 
6

Para los desarrolladores Scala, aquí es función recursiva para ejecutar un análisis completo y mapear de los contenidos de un cubo de AmazonS3 usando el funcionario AWS SDK for Java

import com.amazonaws.services.s3.AmazonS3Client 
import com.amazonaws.services.s3.model.{S3ObjectSummary, ObjectListing, GetObjectRequest} 
import scala.collection.JavaConversions.{collectionAsScalaIterable => asScala} 

def map[T](s3: AmazonS3Client, bucket: String, prefix: String)(f: (S3ObjectSummary) => T) = { 

    def scan(acc:List[T], listing:ObjectListing): List[T] = { 
    val summaries = asScala[S3ObjectSummary](listing.getObjectSummaries()) 
    val mapped = (for (summary <- summaries) yield f(summary)).toList 

    if (!listing.isTruncated) mapped.toList 
    else scan(acc ::: mapped, s3.listNextBatchOfObjects(listing)) 
    } 

    scan(List(), s3.listObjects(bucket, prefix)) 
} 

Para invocar el curry por encima de map() función, simplemente pase el objeto AmazonS3Client ya construido (y debidamente inicializado) (consulte el AWS SDK for Java API Reference oficial), el nombre del depósito y el nombre del prefijo en la lista de los primeros parámetros. También pase la función f() que desea aplicar para asignar cada resumen de objeto en la segunda lista de parámetros.

Por ejemplo

val keyOwnerTuples = map(s3, bucket, prefix)(s => (s.getKey, s.getOwner)) 

devolverá la lista completa de los (key, owner) tuplas en ese cubo/prefijo

o

map(s3, "bucket", "prefix")(s => println(s)) 

como lo haría normalmente enfoque por Monads in Functional Programming

Cuestiones relacionadas