[英]AWS S3 - Listing all objects inside a folder without the prefix
我在检索AWS S3中文件夹内的所有对象(文件名)时遇到问题。 这是我的代码:
ListObjectsRequest listObjectsRequest = new ListObjectsRequest()
.withBucketName(bucket)
.withPrefix(folderName + "/")
.withMarker(folderName + "/")
ObjectListing objectListing = amazonWebService.s3.listObjects(listObjectsRequest)
for (S3ObjectSummary summary : objectListing.getObjectSummaries()) {
print summary.getKey()
}
它返回正确的对象但是带有前缀,例如foldename / filename
我知道我可以使用java或substring来排除前缀,但我只想知道AWS SDK中是否有方法。
那没有。 Linked是所有可用方法的列表。 这背后的原因是S3设计。 S3没有“子文件夹”。 相反,它只是一个文件列表,其中文件名是“前缀”加上您想要的文件名。 GUI显示与存储在“文件夹”中的窗口类似的数据,但S3中没有文件夹逻辑。
最好的办法是用“/”拆分并取出数组中的最后一个对象。
对于Scala开发人员,这里是使用官方AWS SDK for Java执行完整扫描和 AmazonS3存储桶内容映射的递归函数
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))
}
要调用上面的curried map()
函数,只需在第一个参数列表中传递已构造的(并且已正确初始化的)AmazonS3Client对象(请参阅官方AWS SDK for Java API Reference ),存储桶名称和前缀名称。 还要传递要应用的函数f()
以映射第二个参数列表中的每个对象摘要。
例如
map(s3, bucket, prefix) { s => println(s.getKey.split("/")(1)) }
将打印所有文件名(不带前缀)
val tuple = map(s3, bucket, prefix)(s => (s.getKey, s.getOwner, s.getSize))
将返回该bucket /前缀中的(key, owner, size)
元组的完整列表
val totalSize = map(s3, "bucket", "prefix")(s => s.getSize).sum
将返回其内容的总大小(注意在表达式结尾处应用的额外sum()
折叠函数;-)
您可以将map()
与Monads在函数式编程中通常采用的许多其他函数结合起来
这段代码帮助我找到我的桶的子目录。
示例: - “Testing”是我的存储桶名称,其中包含“kdblue@gmail.com”文件夹,然后包含“IMAGE”文件夹,其中包含图像文件。
ArrayList<String> transferRecord = new ArrayList<>();
ListObjectsRequest listObjectsRequest =
new ListObjectsRequest()
.withBucketName(Constants.BUCKET_NAME)
.withPrefix("kdblue@gmail.com" + "/IMAGE");
ObjectListing objects = s3.listObjects(listObjectsRequest);
for (;;) {
List<S3ObjectSummary> summaries =
objects.getObjectSummaries();
if (summaries.size() < 1) {
break;
}
for(int i=0;i<summaries.size();i++){
ArrayList<String> file = new ArrayList<>();
file.add(summaries.get(i).getKey());
transferRecord.add(file);
}
objects = s3.listNextBatchOfObjects(objects);
}
我希望这可以帮助你。
只是为了跟进上面的评论 - “这里它是执行完整扫描和映射的递归函数” - 如果存储桶中有超过1000个密钥,则代码中存在一个错误(如@Eric突出显示)。 修复实际上非常简单,需要将mapped.toList与acc合并。
def map[T](s3: AmazonS3Client, bucket: String, prefix: String)(f: (S3ObjectSummary) => T) = {
def scan_s3_bucket(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) {
acc ::: mapped.toList
} else {
println("list extended, more to go: new_keys '%s', current_length '%s'".format(mapped.length, acc.length))
scan_s3_bucket(acc ::: mapped, s3.listNextBatchOfObjects(listing))
}
}
scan_s3_bucket(List(), s3.listObjects(bucket, prefix))
}
剪下来对我来说效果很好。 参考: https : //codeflex.co/get-list-of-objects-from-s3-directory/
List<String> getObjectslistFromFolder(String bucketName, String folderKey, AmazonS3 s3Client) {
ListObjectsRequest listObjectsRequest = new ListObjectsRequest().withBucketName(bucketName)
.withPrefix(folderKey + "/");
List<String> keys = new ArrayList<String>();
ObjectListing objects = s3Client.listObjects(listObjectsRequest);
for (;;) {
List<S3ObjectSummary> summaries = objects.getObjectSummaries();
if (summaries.size() < 1) {
break;
}
// summaries.forEach(s -> keys.add(s.getKey()));
// changed project compliance to jre 1.8
summaries.forEach(s -> keys.add(s.getKey()));
objects = s3Client.listNextBatchOfObjects(objects);
}
return keys;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.