【问题标题】:Calculate S3 object(folder) size in java在java中计算S3对象(文件夹)的大小
【发布时间】:2021-11-30 20:06:53
【问题描述】:

我在亚马逊 S3 上存储所有类型的文件。在 amazon S3 存储桶中,所有文件都存储在不同的文件夹中,我知道 amazon s3 中没有文件夹的概念。对象仅由它们的键标识。如果我使用“mydocs/personal/profile-pic.jpg”之类的密钥存储任何文件,这意味着将在那里创建两个父文件夹(mydocs 文件夹中的个人文件夹)。

我想计算任何文件夹的大小,例如 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) ,就像尝试解析文件夹对象并计算总大小一样。

标签: java amazon-web-services amazon-s3 aws-sdk


【解决方案1】:

org.apache.hadoop lib 有一个简单的方法

  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和本地文件系统的大小

【讨论】:

    【解决方案2】:

    对于 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))
    }
    

    要调用上述柯里化的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() 与许多其他功能结合起来,就像您通常通过Monads in Functional Programming 实现的那样

    【讨论】:

      【解决方案3】:

      我认为您想获取每个级别的文件夹大小。就像如果您有一个根文件夹 R-Folder 和两个子文件夹 S1.1-Folder、S1.2-Folder,然后 S1.1-Folder 又有三个子文件夹 S1.1.1-Folder、S1.1.2-Folder、S1。 1.3 文件夹。现在你想要每个文件夹的文件夹大小

      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)
      

      我说的对吗?

      您必须保留状态为已完成或未完成的列表文件夹详细信息 - 并递归扫描每个文件夹。并且当内部文件夹成功完成时,您必须更新其对应父级的大小,该父级将更新到相应的父级,并且每次都会持续到根目录。

      【讨论】:

      • 感谢您的回复,您收到了我的问题,但这样做并不合适,因为如果我有数百个文件和文件夹,计算父文件夹大小将花费大量时间。计算所有子文件/文件夹将是递归循环。我需要像我在上面发布的代码一样的解决方案来计算整个存储桶的大小,或者最好将文件和文件夹的大小存储在数据库中并计算所有这些的总和。
      【解决方案4】:

      遇到同样的问题,简单的解决方案是使用:

       ObjectListing objects = listObjects(bucketName,prefix);
      


      其中 prefix 是您的文件夹名称。

      有关更多信息,请参阅以下链接:

      http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/ObjectListing.html

      http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/AmazonS3Client.html

      【讨论】:

        【解决方案5】:

        对于 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;
          }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-17
          • 2012-03-11
          • 1970-01-01
          • 2019-10-14
          • 2011-01-12
          • 2019-01-06
          相关资源
          最近更新 更多