使用Java计算S3对象(文件夹)大小

6
我将各种类型的文件存储在Amazon S3上。在Amazon S3存储桶中,所有文件都存储在不同的文件夹中,我知道Amazon S3中没有文件夹的概念。对象仅由其键标识。如果我使用像“mydocs / personal / profile-pic.jpg”这样的键存储任何文件,则表示将创建两个父文件夹(mydocs文件夹中的personal文件夹)。
我想在Java中计算任何文件夹(如'mydocs')的大小。我使用以下代码计算了存储桶的总大小:
public long calculateBucketSize(String bucketName) {
long totalSize = 0;
    int totalItems = 0;
    ObjectListing objects = listObjects(bucketName);
    do {
        for (S3ObjectSummary objectSummary : objects.getObjectSummaries()) {
            totalSize += objectSummary.getSize();
            totalItems++;
        }
        objects = listNextBatchOfObjects(objects);
    } while (objects.isTruncated());
    System.out.println("Amazon S3 bucket: " + bucketName + " containing "
            + totalItems + " objects with a total size of " + totalSize
            + " bytes.");

    return totalSize;
}

此方法将返回存储桶的总大小。我想计算任何单个文件夹的大小。非常感谢您的帮助。


尝试使用objects=listObjects(bucketName/foldername)来仅遍历文件夹对象并计算总大小。 - Avichal Badaya
6个回答

2

使用 org.apache.hadoop 库可以轻松实现此操作。

最初的回答:Original Answer

  def calculateSize(path: String)(implicit spark: SparkSession): Long = {
    val fsPath = new Path(path)
    val fs = fsPath.getFileSystem(spark.sparkContext.hadoopConfiguration)
    fs.getContentSummary(fsPath).getLength
  }

这个函数可以计算s3、hdfs和本地文件系统中的大小

原始答案翻译成“最初的回答”


1
对于Scala开发人员,这是一个递归函数,可以使用官方AWS SDK for Java执行AmazonS3存储桶内容的全面扫描和映射。请保留HTML标签。
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))
}

要调用上述柯里化的map()函数,只需在第一个参数列表中传递已构建(并正确初始化)的AmazonS3Client对象(请参阅官方AWS SDK for Java API Reference)、存储桶名称和前缀名称。同时,在第二个参数列表中传递您想要应用于映射每个对象摘要的函数f()
例如:
val tuple = map(s3, bucket, prefix)(s => (s.getKey, s.getOwner, s.getSize))

这将返回该存储桶/前缀中所有 (key, owner, size) 元组的完整列表。

或者

map(s3, "bucket", "prefix")(s => s.getSize).sum

将返回该桶/前缀内容的总大小。
您可以像通常使用函数式编程中的单子一样,将map()与许多其他函数相结合使用。

1

对于Java AWS SDK V2,这是一个例子:

  public Long getFolderSize(String bucket, String prefix) {
    ListObjectsV2Request request =
        ListObjectsV2Request.builder().bucket(bucket).prefix(prefix).build();
    ListObjectsV2Iterable list = s3Client.listObjectsV2Paginator(request);
    long totalSize = 0;
    long numberItems = 0;
    for (S3Object object : list.contents()) {
      totalSize += object.size();
      numberItems++;
    }
    logger.info(
        "The size of the folder {}, is {} bytes, number of items {}",
        bucket + prefix,
        totalSize,
        numberItems);
    return totalSize;
  }

0

如何计算磁盘使用量?循环遍历 getObjectSummaries(),并计算每个文件的总数? - Jesper van den Munckhof

0
以下代码获取给定前缀/键中的所有文件并返回总大小。
public Long listS3FolderSize(String bucket, String dirPrefix) {
    Long folderSizeInBytes = 0L;
    List<S3ObjectSummary> objectsListing = getObjectSummaryList(bucket, dirPrefix);
    for (S3ObjectSummary summary: objectsListing) {
        folderSizeInBytes += summary.getSize();
    }

    return folderSizeInBytes;
}

0
我认为您想要获取每个级别文件夹的大小。比如说,如果您有一个根目录 R-Folder 和两个子目录 S1.1-Folder、S1.2-Folder,而 S1.1-Folder 又有三个子目录 S1.1.1-Folder、S1.1.2-Folder、S1.1.3-Folder。现在,您希望获取每个文件夹的文件夹大小。
R-Folder (32MB)
|__S1.1-Folder (22MB)
|  |__S1.1.1-Folder (7MB)
|  |__S1.1.2-Folder (5MB)
|  |__S1.1.3-Folder (10MB)
|
|__S1.2-FOlder (10MB)

我说的对吗?

你需要保留列表文件夹的详细信息,包括状态是否已完成,并递归扫描每个文件夹。当内部文件夹成功完成时,你必须更新其相应父文件夹的大小,该父文件夹将更新到其相应的父文件夹,这将一直持续到根目录。


1
谢谢您的回复,您理解了我的问题,但这不是一个合适的解决方案,因为这样做,如果我有数百个文件和文件夹,计算父文件夹大小将需要大量时间。这将是递归循环来计算所有子文件/文件夹。我需要像我上面发布的代码一样的解决方案来计算整个存储桶的大小,或者更好的方法是将文件和文件夹的大小存储在数据库中并计算它们的总和。 - Haseeb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接