AmazonS3只为一个bucket返回1000个条目,而为另一个bucket返回所有条目(使用JavaSDK)?
我使用下面提到的代码从s3 bucket获取所有文件名的列表。我在s3里有两个桶。对于下面的一个bucket,代码返回所有文件名(超过1000个),但对于另一个bucket,同一代码只返回1000个文件名。我只是不明白发生了什么。 为什么一个bucket运行相同的代码而另一个bucket不运行相同的代码 我的bucket还有层次结构folder/filename.jpgAmazonS3只为一个bucket返回1000个条目,而为另一个bucket返回所有条目(使用JavaSDK)?,java,amazon-s3,Java,Amazon S3,我使用下面提到的代码从s3 bucket获取所有文件名的列表。我在s3里有两个桶。对于下面的一个bucket,代码返回所有文件名(超过1000个),但对于另一个bucket,同一代码只返回1000个文件名。我只是不明白发生了什么。 为什么一个bucket运行相同的代码而另一个bucket不运行相同的代码 我的bucket还有层次结构folder/filename.jpg ObjectListing objects = s3.listObjects("bucket.new.test"); do {
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());
我刚刚将上述代码更改为使用addAll,而不是使用for循环逐个添加对象,这对我很有效:
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());
List keyList=new ArrayList();
ObjectListing object=s3.listObjects(“bucket.new.test”);
keyList=object.getObjectSummaries();
object=s3.ListNextBatchOfObject(对象);
while(object.isTruncated()){
addAll(current.getObjectSummaries());
object=s3.ListNextBatchOfObject(当前);
}
addAll(object.getObjectSummaries());
在这之后,您可以简单地在listkeyList上使用任何迭代器,如果您想要获得所有对象(超过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);
对于Scala开发人员来说,这里是一个递归函数,它使用官方的
import com.amazonaws.services.s3.AmazonS3Client
导入com.amazonaws.services.s3.model.{S3ObjectSummary,ObjectListing,GetObjectRequest}
导入scala.collection.JavaConversions.{collectionAsScalaIterable=>asScala}
defmap[T](s3:AmazonS3Client,bucket:String,prefix:String)(f:(S3ObjectSummary)=>T){
def扫描(acc:List[T],listing:ObjectListing):List[T]={
val summaries=asScala[S3ObjectSummary](listing.getObjectSummaries())
val mapped=(对于(摘要(s.getKey,s.getOwner))
将返回该bucket/前缀中的(key,owner)
元组的完整列表
或
map(s3,“bucket”,“prefix”)(s=>println(s))
正如你通常通过改进@Abhishek的答案来接近的那样。 此代码略短,变量名是固定的 您必须获得对象列表, 将其内容添加到集合中, 然后从列表中获取下一批对象。 重复该操作,直到列表不会被截断
List keyList=new ArrayList();
ObjectListing objects=s3.listObjects(“bucket.new.test”);
addAll(objects.getObjectSummaries());
while(objects.isTruncated()){
objects=s3.listenxtbatchofobjects(objects);
addAll(objects.getObjectSummaries());
}
import com.amazonaws.services.s3.AmazonS3Client
导入com.amazonaws.services.s3.model.{ObjectListing,S3ObjectSummary}
导入scala.collection.JavaConverters_
导入scala.collection.mutable.ListBuffer
defmap[T](s3:AmazonS3Client,bucket:String,prefix:String)(f:(S3ObjectSummary)=>T):列表[T]={
def扫描(acc:ListBuffer[T],列表:ObjectListing):列表[T]={
val r=acc++=listing.getObjectSummaries.asScala.map(f).toList
if(listing.isTruncated)扫描(r,s3.listenxtbatchofobjects(listing))
托利斯特酒店
}
扫描(ListBuffer.empty[T],s3.listObjects(bucket,前缀))
}
第二种方法是使用awssdk-v2
software.amazon.awssdk
s3
2.1.0
import software.amazon.awssdk.services.s3.S3Client
导入software.amazon.awssdk.services.s3.model.{ListObjectsV2Request,S3Object}
导入scala.collection.JavaConverters_
def listObjects[T](s3:s3客户端,bucket:String,
前缀:String,startAfter:String)(f:(S3Object)=>T:List[T]={
val request=ListObjectsV2Request.builder()
.bucket(bucket).前缀(prefix)
.startAfter(startAfter.build())
s3.listObjectsV2Paginator(请求)
阿斯卡拉先生
.flatMap(u.contents().asScala)
.地图(f)
托利斯先生
}
在Scala中:
val first = s3.listObjects("bucket.new.test")
val listings: Seq[ObjectListing] = Iterator.iterate(Option(first))(_.flatMap(listing =>
if (listing.isTruncated) Some(s3.listNextBatchOfObjects(listing))
else None
))
.takeWhile(_.nonEmpty)
.toList
.flatten
默认情况下,API最多返回1000个键名。响应可能包含较少的键,但不会包含更多的键。 更好的实现是使用较新的ListObjectsV2 API:
List<S3ObjectSummary> docList=new ArrayList<>();
ListObjectsV2Request req = new ListObjectsV2Request().withBucketName(bucketName).withPrefix(folderFullPath);
ListObjectsV2Result listing;
do{
listing=this.getAmazonS3Client().listObjectsV2(req);
docList.addAll(listing.getObjectSummaries());
String token = listing.getNextContinuationToken();
req.setContinuationToken(token);
LOG.info("Next Continuation Token for listing documents is :"+token);
}while (listing.isTruncated());
List docList=new ArrayList();
ListObjectsV2Request req=新的ListObjectsV2Request()。带bucketName(bucketName)。带前缀(folderFullPath);
ListObjectsV2Result列表;
做{
清单=this.getAmazonS3Client().listObjectsV2(req);
addAll(listing.getObjectSummaries());
String token=listing.getNextContinuationToken();
请求setContinuationToken(令牌);
LOG.info(“列表文档的下一个延续标记为:“+标记”);
}while(listing.isTruncated());
由@oferei给出的代码运行良好,我支持该代码。但我想指出@Abhishek代码的根本问题。实际上,问题在于您的do-while循环。
如果仔细观察,您将在最后二条语句中获取下一批对象,然后检查是否已耗尽文件的总列表变为false,则中断循环,不处理最后的X%1000条记录。例如:如果总共有2123条记录,则最终将获取1000条,然后是1000条,即2000条记录。您将错过123条记录,因为在检查isTruncated值后处理下一批时,isTruncated值将中断循环
抱歉,我不能发表评论,否则我会对投票结果发表评论。我建议使用keyList.addAll(x)而不是分配给keyList。这样你就不会修改ObjectList的私有成员
List<S3ObjectSummary> docList=new ArrayList<>();
ListObjectsV2Request req = new ListObjectsV2Request().withBucketName(bucketName).withPrefix(folderFullPath);
ListObjectsV2Result listing;
do{
listing=this.getAmazonS3Client().listObjectsV2(req);
docList.addAll(listing.getObjectSummaries());
String token = listing.getNextContinuationToken();
req.setContinuationToken(token);
LOG.info("Next Continuation Token for listing documents is :"+token);
}while (listing.isTruncated());