2012-10-12 23 views
8

我使用下面提到的代碼來獲取s3存儲桶中所有文件名的列表。我在S3有兩個桶。對於下面的代碼段之一,將返回所有文件名(超過1000個),但是相同的代碼只會爲另一個存儲段返回1000個文件名。我只是不知道發生了什麼。 爲什麼同一個代碼運行一個桶而不是其他?亞馬遜S3僅爲一個存儲桶返回1000個條目,併爲其他存儲桶返回1000個條目(使用java sdk)?

另外我的桶有層次結構文件夾/ 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()); 

回答

4

性改進方法@阿披希克自己的答案。 此代碼略短。還修復了變量名稱。

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

但是根源是什麼?爲什麼相同的代碼只能處理一個案件,而不能處理另一個案件? – morsik

+0

這是一個很好的問題,我沒有答案。我只拿@ Abhishek的代碼並「修復」它。我唯一的猜測是它是一個桶的財產。 – oferei

+1

我的s3 java API的「舊」版本有同樣的問題。亞馬遜推出了「v2」,它應該解決這個問題:http://docs.aws.amazon.com/AmazonS3/latest/dev/ListingObjectKeysUsingJava。html 請注意,它使用's3client.listObjectsV2'和'req.setContinuationToken(result.getNextContinuationToken())'。最後一個應該對s3進行單獨的基礎REST GET調用(因爲默認情況下,單個get返回最多1000個鍵,http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html) – morsik

4

我剛剛更改上面的代碼中使用,而不是使用循環逐個對象添加一個中的addAll,它爲我工作。代碼更改爲:

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

之後,你可以簡單地使用任何iterater在列表密鑰列表

+0

我建議使用keyList.addAll(x)而不是分配給keyList。這樣你就不會在稍後使用addAll修改ObjectListing的私有成員(由getObjectSummaries返回)。而且,既然你已經在第一行中分配了一個列表,你就全部設置好了。 – oferei

1

如果你想獲得所有的對象(超過1000個密鑰),你需要發送另一個包含S3的最後一個密鑰。這是代碼。

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

對於斯卡拉開發人員,在這裏它是執行全掃描和使用官方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)) 
} 

要調用上述咖喱地圖的AmazonS3桶的內容遞歸函數map()函數,只需將已構建(且已正確初始化)的AmazonS3Client對象(請參閱官方AWS SDK for Java API Reference),桶名稱和前綴名稱傳遞到第一個參數列表中。還要通過您想要應用的功能f()來映射第二個參數列表中的每個對象摘要。

例如

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

將返回該桶/前綴(key, owner)元組的完整列表

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

,你通常會通過Monads in Functional Programming