如何计算Bucket中某个Prefix下所有文件的存储大小?

通过OSS的清单或者列举文件的功能,您可以统计指定Prefix(前缀或者目录)下所有文件的存储容量。通过统计存储容量,有助于您了解存储资源的使用情况,为优化存储成本和提升存储效率提供支撑。

方式对比

方式

描述

使用场景

清单

周期性获取Bucket的Object信息及其元数据的清单文件。支持扫描指定Prefix的Object、清单内容支持自定义、例如只导出Object大小和存储类型等。清单文件以CSV格式保存。

  • Bucket内Object数量较多(例如100亿),需要定期获取Object列表信息的场景,例如了解不同业务的空间使用情况。

  • 需要存档某些Object元数据供后续使用

列举文件

通过ListObjects实时获取Bucket的Object列表,可通过Prefix、最大返回数量等条件来灵活控制查询的结果,适合特定条件下的快速查询。

  • Bucket中Object数量较少(例如几千个Object)

  • 需要频繁查询实时Object信息的场景,例如文件上传后需要快速验证文件是否存在

使用清单

例如,您希望导出Bucket内前缀(Prefix)为bill/的所有文件的清单,并统计bill/前缀所有文件的总存储容量。

  1. 配置清单规则。

    1. 在对象存储OSS控制台的Bucket列表页面,单击目标Bucket。

    2. 在左侧导航栏,选择数据管理 > Bucket 清单

    3. Bucket 清单页面,单击创建清单

    4. 设置清单报告规则面板,按以下说明配置各项参数,其他参数保留默认配置,然后单击确定

      bill.jpg

      参数

      说明

      规则名称

      自定义清单任务的名称,本示例为inventory001。

      存储清单 Bucket

      选择当前Bucket名称。

      清单报告导出周期

      选择每天

      清单内容

      选中Object大小

      按前缀匹配

      设置为bill/

  2. 通过清单文件统计bill前缀所有文件的总存储容量。

    1. 文件列表页面,找到Bucket名称/清单ID/data/路径下以csv.gz结尾的清单文件。

      bill.jpg

    2. 单击清单文件右侧的more > 下载,将文件下载到本地路径,并完成解压。

    3. 统计文件存储容量大小。

      打开csv清单文件,文件中的C列数据总大小即为bill前缀所有文件的总存储容量,单位为字节。

  3. (可选)删除清单规则。

    • 设置清单报告导出周期为每天,能够满足您快速获取清单文件的需求。在清单规则未被删除前,OSS会按照清单规则每天生成清单文件。清单文件会产生存储费用。为避免产生不必要的费用,如果您不需要频繁获取最新的清单文件,建议您在首次生成清单文件后,及时删除相应的清单规则。

      bill.jpg

    • 如果您需要周期性频繁获取最新的清单文件,则保留当前配置的清单规则。

列举文件

使用阿里云SDK

以下提供常见SDK列举指定Prefix下所有文件的总存储容量的示例代码。

Java

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;

import java.util.List;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 指定Prefix。
        String keyPrefix = "bill/";
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
        // 初始化文件总大小变量。
        long totalSize = 0L;

        try {
            ObjectListing objectListing = null;
            do {
                // 列举文件。
                ListObjectsRequest request = new ListObjectsRequest(bucketName).withDelimiter("/").withPrefix(keyPrefix);
                if (objectListing != null) {
                    request.setMarker(objectListing.getNextMarker());
                }
                objectListing = ossClient.listObjects(request);
                List<String> folders = objectListing.getCommonPrefixes();
                for (String folder : folders) {
                    long folderSize = calculateFolderLength(ossClient, bucketName, folder);
                    totalSize += folderSize;
                    System.out.println(folder + " : " + (folderSize / 1024) + "KB");
                }
                List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
                for (OSSObjectSummary s : sums) {
                    totalSize += s.getSize();
                    System.out.println(s.getKey() + " : " + (s.getSize() / 1024) + "KB");
                }
            } while (objectListing.isTruncated());
        
            System.out.println("Total Size: " + (totalSize / 1024) + "KB");
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    // 获取指定Prefix下所有文件的总存储容量。
    private static long calculateFolderLength(OSS ossClient, String bucketName, String folder) {
        long size = 0L;
        ObjectListing objectListing = null;
        do {
            // MaxKey默认值为100,最大值为1000。
            ListObjectsRequest request = new ListObjectsRequest(bucketName).withPrefix(folder).withMaxKeys(1000);
            if (objectListing != null) {
                request.setMarker(objectListing.getNextMarker());
            }
            objectListing = ossClient.listObjects(request);
            List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
            for (OSSObjectSummary s : sums) {
                size += s.getSize();
            }
        } while (objectListing.isTruncated());
        return size;
    }
}

Python

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
# 填写Bucket名称,例如examplebucket。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')
# 指定Prefix。
prefix = 'bill/'

def calculate_storage_size(prefix):
    total_size = 0

    # 列举以指定Prefix开头的所有Object.
    for obj in oss2.ObjectIterator(bucket, prefix=prefix):
        total_size += obj.size  # 累加Object的大小。

    return total_size

if __name__ == "__main__":
    size = calculate_storage_size(prefix)
    print(f'Total size of objects with prefix "{prefix}": {size} bytes')

使用命令行工具ossutil

您可以使用ossutil查看某个prefix下所有文件的总存储容量。具体步骤,请参见查询指定目录下所有Object的大小

相关文档