我正在尝试在folders
存储桶中列出所有所谓的sub-folders
和s3
。
现在,由于我试图递归列出路径中的所有文件夹,因此我没有使用withDelimeter()
函数。
所有所谓的folder
名称都应以/
结尾,这是列出所有文件夹和子文件夹的逻辑。
这是scala
代码(故意不在此处粘贴catch
代码):
val awsCredentials = new BasicAWSCredentials(awsKey, awsSecretKey)
val client = new AmazonS3Client(awsCredentials)
def listFoldersRecursively(bucketName: String, fullPath: String): List[String] = {
try {
val objects = client.listObjects(bucketName).getObjectSummaries
val listObjectsRequest = new ListObjectsRequest()
.withPrefix(fullPath)
.withBucketName(bucketName)
val folderPaths = client
.listObjects(listObjectsRequest)
.getObjectSummaries()
.map(_.getKey)
folderPaths.filter(_.endsWith("/")).toList
}
}
Here's the structure of my bucket
through an s3 client
Here's the list I am getting using this scala
code
在没有任何明显的模式的情况下,检索到的文件夹列表中缺少许多文件夹。 我没有使用
client.listObjects(listObjectsRequest).getCommonPrefixes.toList
因为某种原因它返回了空列表。
PS:由于是新用户,无法直接在帖子中添加照片。
答案 0 :(得分:2)
好吧,以防万一将来有人遇到相同的问题,我使用的替代逻辑是上面@Michael所建议的,我遍历了所有键,并在最后一次出现/
时使用了它们。返回列表的第一个index
+ /
是文件夹的键,并将其附加到另一个列表。最后,返回了我要附加到的unique
列表。这给了我所有folders
和sub-folders
在某个前缀位置。
请注意,我没有使用CommonPrefixes
是因为我没有使用任何delimiter
,那是因为我不想在特定级别使用folders
的列表但相反,recursively
获取所有folders
和sub-folders
def listFoldersRecursively(bucketName: String, fullPath: String): List[String] = {
try {
val objects = client.listObjects(bucketName).getObjectSummaries
val listObjectsRequest = new ListObjectsRequest()
.withPrefix(fullPath)
.withBucketName(bucketName)
val folderPaths = client.listObjects(listObjectsRequest)
.getObjectSummaries()
.map(_.getKey)
.toList
val foldersList: ArrayBuffer[String] = ArrayBuffer()
for (folderPath <- folderPaths) {
val split = folderPath.splitAt(folderPath.lastIndexOf("/"))
if (!split._1.equals(""))
foldersList += split._1 + "/"
}
foldersList.toList.distinct
提示:由于不相关,故意丢失了捕获块。
答案 1 :(得分:1)
没有任何明显的模式,检索到的文件夹列表中缺少许多文件夹。
这是您的问题:您假设应该始终存在键的结尾为/
的对象以象征文件夹。
这是一个错误的假设。只有通过S3控制台或API创建它们后,它们才会在那里。没有理由期望它们,因为S3实际上不需要它们或将它们用于任何用途,并且S3服务本身不会自发地创建它们。
如果您使用API上载密钥为foo/bar.txt
的对象,则不会将foo/
文件夹创建为单独的对象。为了方便起见,它将在控制台中显示为文件夹,但是除非您有意创建了该文件夹,否则它不会存在。
当然,通过控制台上传此类对象的唯一方法是“创建”文件夹,除非该文件夹已经出现-但出现在控制台中不一定等于作为一个独特的对象存在。
对endsWith("/")
进行过滤是无效逻辑。
这就是为什么如果指定了CommonPrefixes
和delimiter
,则基础API在每个ListObjects响应中都包含prefix
的原因。这是下一级别的“文件夹”的列表,您必须递归向下钻取才能找到下一级。
如果指定前缀,则所有在前缀与该前缀后的第一个出现的定界符之间包含相同字符串的键都归为一个称为CommonPrefixes的结果元素。如果未指定prefix参数,则子字符串从键的开头开始。分组在CommonPrefixes结果元素下的键不会在响应的其他地方返回。
https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html
您需要使用您使用或使用的任何库来访问此功能,或者需要迭代整个键列表并使用字符串拆分在/
边界上发现实际的公共前缀。
答案 2 :(得分:0)
listObjects
函数(和其他函数)正在分页,每次最多返回100个条目。
来自文档:
由于存储桶可以包含几乎无限数量的密钥,因此 列表查询的完整结果可能非常大。管理 大型结果集,Amazon S3使用分页将它们分成 多个回应。始终检查ObjectListing.isTruncated() 查看返回的清单是否完整或附加的方法 需要致电才能获得更多结果。或者,使用 AmazonS3Client.listNextBatchOfObjects(ObjectListing)方法很简单 获取对象列表的下一页的方法。