全部產品
Search
文件中心

Object Storage Service:使用儲存空間清單

更新時間:Nov 18, 2025

當儲存空間(Bucket)中的檔案(Object)數量達到數百萬甚至上百億時,通過 ListObjects 介面逐一列舉會變得非常緩慢且成本高昂。儲存空間清單功能專為此類海量Object情境設計,它能夠非同步、定期地掃描 Bucket,並產生一份包含指定對象中繼資料(如大小、儲存類型、加密狀態等)的資訊清單檔,可靈活應用於多種情境,如:資產盤點、成本分析、資料合規審計、批量處理任務的輸入準備等。

工作原理

建立清單規則後,OSS 會在指定周期(每天或每周)自動執行清單產生任務。該任務在後台非同步運行,不影響對 Bucket 的正常訪問。其工作流程遵循以下步驟:

  1. 擷取許可權:OSS 通過扮演一個預先授權的 RAM 角色,來獲得掃描源儲存桶和寫入目標儲存桶的許可權。

  2. 掃描對象:OSS 根據規則中定義的篩選條件(如對象首碼、版本狀態、建立時間或大小),掃描源儲存桶中的所有匹配對象。

  3. 產生清單報告:OSS 將掃描結果彙總產生清單報告,並以 Gzip 壓縮的 CSV 檔案格式,寫入指定的 Bucket 中。

使用此功能時,請注意:

  • 報告快照:清單報告是任務啟動時刻儲存桶狀態的快照。在掃描執行期間的對象變更(如新增、覆蓋或刪除)不保證會反映在當次的報告中。

  • 首份清單會在配置後立即執行,後續按客戶設定的每日或每周的周期在北京時間淩晨批量執行,匯出延遲受對象數量與任務隊列影響。

步驟一:配置許可權

根據當前使用的身份,需要完成的授權步驟有所不同:

  • 阿里雲帳號:只需要 建立 RAM 角色並為其授權,以便 OSS 服務可以扮演該角色。

  • RAM 使用者:需要管理員或主賬戶先為您的帳號授權,獲得建立清單和管理 RAM 角色的許可權,再建立 RAM 角色並為其授權

第一步:為 RAM 使用者授權(如適用)

此步驟旨在授予 RAM 使用者配置清單規則及建立後續所需 RAM 角色的許可權。

如果是阿里雲帳號,可跳過此步驟,直接進入第二步。

安全建議:由於授予 RAM 使用者建立角色(ram:CreateRole)等許可權存在一定的安全風險,推薦通過阿里雲帳號預先建立好所需的 RAM 角色。授權完成後,RAM 使用者可以直接在建立清單規則時選用該角色,無需自己建立,這是一種更安全的實踐。如果仍需為 RAM 使用者授予建立角色的許可權,請按以下步驟操作:

  1. 建立自訂權限原則 通過指令碼編輯模式建立以下自訂策略。

    以下策略中的 oss:ListBuckets 許可權僅在通過控制台操作時需要。如果通過 SDK 或 ossutil 等工具訪問,則無需此許可權。
    {
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "oss:PutBucketInventory",
                    "oss:GetBucketInventory",
                    "oss:DeleteBucketInventory",
                    "oss:ListBuckets",
                    "ram:CreateRole",
                    "ram:AttachPolicyToRole",
                    "ram:GetRole",
                    "ram:ListPoliciesForRole"
                ],
                "Resource": "*"
            }
        ],
        "Version": "1"
    }

    提示:如果當前 RAM 使用者已擁有 AliyunOSSFullAccess 系統許可權,則僅需為其補充授予角色管理的相關許可權即可:

    {
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "ram:CreateRole",
                    "ram:AttachPolicyToRole",
                    "ram:GetRole",
                    "ram:ListPoliciesForRole"
                ],
                "Resource": "*"
            }
        ],
        "Version": "1"
    }
  2. 為 RAM 使用者授權 將剛剛建立的自訂策略授予目標 RAM 使用者

第二步:建立並配置 RAM 角色

允許 OSS 服務將產生的清單報告檔案寫入目標 Bucket。

  1. 前往 RAM 控制台,建立角色。選擇信任的實體類型為雲端服務,信任主體名稱選擇Object Storage Service

  2. 為該角色建立並附加一個自訂權限原則。策略內容如下,將 your-destination-bucket 替換為實際用於存放清單報告的 Bucket 名稱。

    {
      "Version": "1",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": "oss:PutObject",
          "Resource": [
            "acs:oss:*:*:your-destination-bucket/*" 
          ]
        }
      ]
    }
    KMS 加密:如果計劃使用 KMS 祕密金鑰加密資訊清單檔,請務必為RAM 角色額外授予 AliyunKMSFullAccess 許可權或更精細的 KMS 相關許可權。
  3. 記錄下該角色的 ARN(例如 acs:ram::1234567890:role/oss-inventory-role),後續步驟將用到。

安全建議:當通過控制台首次配置清單規則時,系統會引導自動建立一個名為 AliyunOSSRole 的服務關聯角色。不推薦在生產環境中使用控制台自動建立的AliyunOSSRole。該角色擁有對所有 Bucket 的完全系統管理權限,存在較大安全風險,僅建議在臨時測試環境中使用。

步驟二:配置清單規則

可以通過 OSS 控制台、SDK 或命令列工具 ossutil 等進行配置,設定清單的掃描範圍、頻率、報告內容等。

控制台

  1. 登入 OSS 管理主控台

  2. 進入需要產生清單的源 Bucket,在左側導覽列選擇 資料管理 > Bucket 清單

  3. Bucket 清單頁面,單擊建立清單

  4. 設定清單報告規則面板,按以下說明配置各項參數。

    參數

    說明

    狀態

    設定清單任務的狀態,選擇啟動

    規則名稱

    設定清單任務的名稱。只能包含小寫字母、數字、短劃線(-),且不能以短劃線(-)開頭或結尾。

    儲存清單 Bucket

    選擇儲存資訊清單檔的Bucket。配置清單的 Bucket 與存放清單 Bucket 必須同帳號、同地區。

    清單報告儲存路徑

    設定清單報告的儲存路徑。

    • 若需將報告儲存到儲存空間 examplebucket 的 exampledir1 路徑,請填寫 exampledir1/,指定路徑在 Bucket 中不存在時,OSS 會自動建立該路徑。

    • 若留空,報告將儲存在根目錄。

    重要

    為避免影響OSS-HDFS服務的正常使用或者引發資料汙染的風險,在開通了OSS-HDFS服務的Bucket設定清單報告規則時,禁止將清單報告目錄填寫為.dlsdata/

    清單報告匯出周期

    設定清單報告的組建循環。可選擇每周每天。檔案數超百億時,建議選擇每周以降低成本和掃描壓力。

    清單報告加密選項

    選擇是否加密資訊清單檔。

    清單內容

    選擇希望匯出的檔案資訊,包括Object大小儲存類型最後更新日期ETag分區上傳狀態加密狀態Object ACL標籤個數檔案類型Crc64

    按首碼匹配

    可選。用於僅掃描指定首碼下的檔案,例如 exampledir1/。留空則掃描整個 Bucket。如果設定的首碼沒有匹配Bucket內的任意Object,則不產生資訊清單檔。

    配置進階篩選功能

    重要

    僅華北1(青島)、華北5(呼和浩特)和德國(法蘭克福)地區支援配置以下過濾選項。

    如果需要根據檔案大小、儲存類型等條件過濾匯出的檔案,需要開啟配置進階篩選功能開關。

    支援的過濾選項說明如下:

    • 時間範圍:設定待匯出檔案最後一次修改的起始日期和結束日期,時間精確到秒。

    • 檔案大小範圍:設定待匯出檔案的檔案大小最小值和最大值。

      說明

      設定檔案大小範圍時,確保檔案大小的最小值以及最大值均大於0 B,且最大值不超過48.8 TB。

    • 儲存類型:設定待匯出哪些儲存類型的檔案。可以選擇匯出標準儲存、低頻訪問、Archive Storage、冷Archive Storage以及深度冷Archive Storage的檔案。

    對象版本

    若 Bucket 開啟了版本控制,可選擇匯出目前的版本所有版本

  5. 選中我知曉並同意授予阿里雲 OSS 服務訪問 Bucket 資源的許可權,然後單擊確定

    涉及Object較多時,產生資訊清單檔需要一定的時間。可以通過兩種方式判斷是否已產生資訊清單檔,詳情請參見如何判斷是否已產生資訊清單檔?

SDK

以下僅列舉常見SDK配置Bucket清單的程式碼範例。關於其他SDK的配置Bucket清單程式碼範例,請參見SDK簡介

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import java.util.ArrayList;
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";
        // 填寫存放清單結果的Bucket名稱。
        String destBucketName ="yourDestinationBucketName";
        // 填寫Bucket所有者授予的賬戶ID。
        String accountId ="yourDestinationBucketAccountId";
        // 填寫具有讀取源Bucket所有檔案和向目標Bucket寫入檔案許可權的角色名稱。
        String roleArn ="yourDestinationBucketRoleArn";
        // 填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為cn-hangzhou。
        String region = "cn-hangzhou";

        // 建立OSSClient執行個體。
        // 當OSSClient執行個體不再使用時,調用shutdown方法以釋放資源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            // 建立清單配置。
            InventoryConfiguration inventoryConfiguration = new InventoryConfiguration();

            // 設定清單規則名稱。
            String inventoryId = "testid";
            inventoryConfiguration.setInventoryId(inventoryId);

            // 設定清單中包含的Object屬性。
            List<String> fields = new ArrayList<String>();
            fields.add(InventoryOptionalFields.Size);
            fields.add(InventoryOptionalFields.LastModifiedDate);
            fields.add(InventoryOptionalFields.IsMultipartUploaded);
            fields.add(InventoryOptionalFields.StorageClass);
            fields.add(InventoryOptionalFields.ETag);
            fields.add(InventoryOptionalFields.EncryptionStatus);
            inventoryConfiguration.setOptionalFields(fields);

            // 設定清單的產生計劃,以下樣本為每周一次。其中,Weekly表示每周一次,Daily表示每天一次。
            inventoryConfiguration.setSchedule(new InventorySchedule().withFrequency(InventoryFrequency.Weekly));

            // 設定清單中包含的Object的版本為目前的版本。如果設定為InventoryIncludedObjectVersions.All則表示Object的所有版本在版本控制狀態下生效。
            inventoryConfiguration.setIncludedObjectVersions(InventoryIncludedObjectVersions.Current);

            // 清單配置是否啟用的標識,取值為true或者false,設定為true表示啟用清單配置,設定為false表示關閉清單配置。
            inventoryConfiguration.setEnabled(true);

            // 設定清單篩選規則,指定篩選Object的首碼。
            InventoryFilter inventoryFilter = new InventoryFilter().withPrefix("obj-prefix");
            inventoryConfiguration.setInventoryFilter(inventoryFilter);

            // 建立存放清單結果的目標Bucket配置。
            InventoryOSSBucketDestination ossInvDest = new InventoryOSSBucketDestination();
            // 設定存放清單結果的儲存路徑首碼。
            ossInvDest.setPrefix("destination-prefix");
            // 設定清單格式。
            ossInvDest.setFormat(InventoryFormat.CSV);
            // 設定目標Bucket的使用者accountId。
            ossInvDest.setAccountId(accountId);
            // 設定目標Bucket的roleArn。
            ossInvDest.setRoleArn(roleArn);
            // 設定目標Bucket的名稱。
            ossInvDest.setBucket(destBucketName);

            // 如果需要使用KMS加密清單,請參考如下設定。
            // InventoryEncryption inventoryEncryption = new InventoryEncryption();
            // InventoryServerSideEncryptionKMS serverSideKmsEncryption = new InventoryServerSideEncryptionKMS().withKeyId("test-kms-id");
            // inventoryEncryption.setServerSideKmsEncryption(serverSideKmsEncryption);
            // ossInvDest.setEncryption(inventoryEncryption);

            // 如果需要使用OSS服務端加密清單,請參考如下設定。
            // InventoryEncryption inventoryEncryption = new InventoryEncryption();
            // inventoryEncryption.setServerSideOssEncryption(new InventoryServerSideEncryptionOSS());
            // ossInvDest.setEncryption(inventoryEncryption);

            // 設定清單的目的地。
            InventoryDestination destination = new InventoryDestination();
            destination.setOssBucketDestination(ossInvDest);
            inventoryConfiguration.setDestination(destination);

            // 上傳清單配置。
            ossClient.setBucketInventoryConfiguration(bucketName, inventoryConfiguration);
        } 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();
            }
        }
    }
}
const OSS = require('ali-oss');

const client = new OSS({
  // yourregion填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為oss-cn-hangzhou。
  region: 'yourregion',
  // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  // 填寫儲存空間名稱。
  bucket: 'yourbucketname'
});

const inventory = {
  // 設定清單配置ID。
  id: 'default', 
  // 清單配置是否啟用的標識,取值為true或false。
  isEnabled: false, 
  //(可選)設定清單篩選規則,指定篩選object的首碼。
  prefix: 'ttt',
  OSSBucketDestination: {
     // 設定清單格式。
    format: 'CSV',
   // 目標Bucket擁有者的帳號ID。
    accountId: '<Your AccountId>', 
   // 目標Bucket的角色名稱。
    rolename: 'AliyunOSSRole',
    // 目標Bucket的名稱。
    bucket: '<Your BucketName>',
    //(可選)清單結果的儲存路徑首碼。
    prefix: '<Your Prefix>',
    // 如果需要使用SSE-OSS加密清單,請參考以下代碼。
    //encryption: {'SSE-OSS': ''},
    // 如果需要使用SSE-KMS加密清單,請參考以下代碼。
           /*
            encryption: {
      'SSE-KMS': {
        keyId: 'test-kms-id',
      };, 
    */
  },
  // 設定清單的產生計劃,WEEKLY對應每周一次,DAILY對應每天一次。
  frequency: 'Daily', 
  // 設定清單結果中包含了Object的所有版本, 如果設定為Current,則表示僅包含Object的目前的版本。
  includedObjectVersions: 'All', 
  optionalFields: {
    //(可選)設定清單中包含的Object屬性。
    field: ["Size", "LastModifiedDate", "ETag", "StorageClass", "IsMultipartUploaded", "EncryptionStatus"]
  },
}

async function putInventory(){
  // 需要添加清單配置的Bucket名稱。
  const bucket = '<Your BucketName>'; 
        try {
    await client.putBucketInventory(bucket, inventory);
    console.log('清單配置添加成功')
  } catch(err) {
    console.log('清單配置添加失敗: ', err);
  }
}

putInventory()
import argparse
import alibabacloud_oss_v2 as oss

# 建立命令列參數解析器,並描述指令碼用途:設定儲存空間清單(Inventory)
parser = argparse.ArgumentParser(description="put bucket inventory sample")

# 定義命令列參數,包括必需的地區、儲存空間名稱、endpoint、使用者ID、角色ARN以及清單名稱
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--user_id', help='User account ID.', required=True)
parser.add_argument('--arn', help='The Alibaba Cloud Resource Name (ARN) of the role that has the permissions to read all objects from the source bucket and write objects to the destination bucket. Format: `acs:ram::uid:role/rolename`.', required=True)
parser.add_argument('--inventory_id', help='The name of the inventory.', required=True)

def main():
    # 解析命令列參數,擷取使用者輸入的值
    args = parser.parse_args()

    # 從環境變數中載入訪問憑證資訊,用於身分識別驗證
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK預設配置建立設定物件,並設定認證提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider

    # 設定設定物件的地區屬性,根據使用者提供的命令列參數
    cfg.region = args.region

    # 如果提供了自訂endpoint,則更新設定物件中的endpoint屬性
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用上述配置初始化OSS用戶端,準備與OSS互動
    client = oss.Client(cfg)

    # 發送請求以配置指定儲存空間的清單設定
    result = client.put_bucket_inventory(oss.PutBucketInventoryRequest(
            bucket=args.bucket,  # 儲存空間名
            inventory_id=args.inventory_id,  # 儲存空間清單ID
            inventory_configuration=oss.InventoryConfiguration(
                included_object_versions='All',  # 包含所有版本的對象
                optional_fields=oss.OptionalFields(
                    fields=[  # 可選欄位,如大小和最後修改日期
                        oss.InventoryOptionalFieldType.SIZE,
                        oss.InventoryOptionalFieldType.LAST_MODIFIED_DATE,
                    ],
                ),
                id=args.inventory_id,  # 儲存空間清單ID
                is_enabled=True,  # 啟用儲存空間清單
                destination=oss.InventoryDestination(
                    oss_bucket_destination=oss.InventoryOSSBucketDestination(
                        format=oss.InventoryFormatType.CSV,  # 輸出格式為CSV
                        account_id=args.user_id,  # 使用者賬戶ID
                        role_arn=args.arn,  # 角色ARN,具有讀取源儲存空間和寫入目標儲存空間的許可權
                        bucket=f'acs:oss:::{args.bucket}',  # 目標儲存空間
                        prefix='aaa',  # 資訊清單檔首碼
                    ),
                ),
                schedule=oss.InventorySchedule(
                    frequency=oss.InventoryFrequencyType.DAILY,  # 清單頻率,這裡設定為每天
                ),
                filter=oss.InventoryFilter(
                    lower_size_bound=1024,  # 對象大小下限(位元組)
                    upper_size_bound=1048576,  # 對象大小上限(位元組)
                    storage_class='ColdArchive',  # 儲存類別篩選條件
                    prefix='aaa',  # 對象首碼篩選條件
                    last_modify_begin_time_stamp=1637883649,  # 最後修改時間戳記開始範圍
                    last_modify_end_time_stamp=1638347592,  # 最後修改時間戳記結束範圍
                ),
            ),
    ))

    # 列印操作結果的狀態代碼和請求ID,以便確認請求狀態
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
    )

# 當此指令碼被直接執行時,調用main函數開始處理邏輯
if __name__ == "__main__":
    main()  # 指令碼進入點,控製程序流程從這裡開始
using Aliyun.OSS;
using Aliyun.OSS.Common;

// yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "yourEndpoint";
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// 填寫Bucket名稱。
var bucketName = "examplebucket";
// 填寫Bucket所有者授予的賬戶ID。
var accountId ="yourDestinationBucketAccountId";
// 填寫具有讀取源Bucket所有檔案和向目標Bucket寫入檔案許可權的角色名稱。
var roleArn ="yourDestinationBucketRoleArn";
// 填寫存放清單結果的Bucket名稱。
var destBucketName ="yourDestinationBucketName";
// 填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。
const string region = "cn-hangzhou";

// 建立ClientConfiguration執行個體,按照您的需要修改預設參數。
var conf = new ClientConfiguration();

// 設定v4簽名。
conf.SignatureVersion = SignatureVersion.V4;

// 建立OssClient執行個體。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);
try
{
    // 添加Bucket清單。
    var config = new InventoryConfiguration();
    // 設定清單規則名稱。
    config.Id = "report1";
    // 清單配置是否啟用的標識,取值為true或false。設定為true,表示啟用清單配置。
    config.IsEnabled = true;
    // 設定清單篩選規則,指定篩選Object的首碼。
    config.Filter = new InventoryFilter("filterPrefix");
    // 建立清單的bucket目的地配置。
    config.Destination = new InventoryDestination();
    config.Destination.OSSBucketDestination = new InventoryOSSBucketDestination();
    // 設定清單格式。
    config.Destination.OSSBucketDestination.Format = InventoryFormat.CSV;
    // 存放清單結果的目標Bucket的使用者accountId。
    config.Destination.OSSBucketDestination.AccountId = accountId;
    // 存放清單結果的目標Bucket的roleArn。
    config.Destination.OSSBucketDestination.RoleArn = roleArn;
    // 存放清單結果的目標Bucket名稱。
    config.Destination.OSSBucketDestination.Bucket = destBucketName;
    // 設定存放清單結果的儲存路徑首碼。
    config.Destination.OSSBucketDestination.Prefix = "prefix1";
    
    // 設定清單的產生計劃,以下樣本為每周一次。其中,Weekly對應每周一次,Daily對應每天一次。
    config.Schedule = new InventorySchedule(InventoryFrequency.Daily);
    // 設定清單中包含的object的版本為目前的版本。如果設定為InventoryIncludedObjectVersions.All則表示object的所有版本,在版本控制狀態下生效。
    config.IncludedObjectVersions = InventoryIncludedObjectVersions.All;
    
    // 設定清單中包含的Object屬性。
    config.OptionalFields.Add(InventoryOptionalField.Size);
    config.OptionalFields.Add(InventoryOptionalField.LastModifiedDate);
    config.OptionalFields.Add(InventoryOptionalField.StorageClass);
    config.OptionalFields.Add(InventoryOptionalField.IsMultipartUploaded);
    config.OptionalFields.Add(InventoryOptionalField.EncryptionStatus);
    config.OptionalFields.Add(InventoryOptionalField.ETag);
    var req = new SetBucketInventoryConfigurationRequest(bucketName, config);
    client.SetBucketInventoryConfiguration(req);
    Console.WriteLine("Set bucket:{0} InventoryConfiguration succeeded", bucketName);
}
catch (OssException ex)
{
    Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}",
        ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS帳號資訊。*/
            
    /* yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    /* yourRegion填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。*/
    std::string Region = "yourRegion";
    /* 填寫Bucket名稱,例如examplebucket。*/
    std::string BucketName = "examplebucket";

    /* 初始化網路等資源。*/
    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    /* 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);

    InventoryConfiguration inventoryConf;
    /* 指定清單規則名稱,該名稱在當前Bucket下必須全域唯一。*/
    inventoryConf.setId("inventoryId");

    /* 清單配置是否啟用的標識,可選值為true或false。*/
    inventoryConf.setIsEnabled(true);

    /* (可選)清單篩選的首碼。指定首碼後,清單將篩選出符合首碼的Object。*/
    inventoryConf.setFilter(InventoryFilter("objectPrefix"));

    InventoryOSSBucketDestination dest;
    /* 匯出資訊清單檔的檔案格式。*/
    dest.setFormat(InventoryFormat::CSV);
    /* 儲存空間擁有者的賬戶UID。*/
    dest.setAccountId("10988548********");
    /* 指定角色名稱,該角色需要擁有讀取源儲存空間所有檔案以及向目標儲存空間寫入檔案的許可權,格式為acs:ram::uid:role/rolename。*/
    dest.setRoleArn("acs:ram::10988548********:role/inventory-test");
    /* 存放匯出的資訊清單檔的儲存空間。*/
    dest.setBucket("yourDstBucketName");
    /* 資訊清單檔的儲存路徑首碼。*/
    dest.setPrefix("yourPrefix");
    /* (可選)資訊清單檔的加密方式, 可選SSEOSS或者SSEKMS方式加密。*/
    //dest.setEncryption(InventoryEncryption(InventorySSEOSS()));
    //dest.setEncryption(InventoryEncryption(InventorySSEKMS("yourKmskeyId")));
    inventoryConf.setDestination(dest);

    /* 資訊清單檔匯出的周期, 可選為Daily或者Weekly。*/
    inventoryConf.setSchedule(InventoryFrequency::Daily);

    /* 是否在清單中包含Object版本資訊, 可選為All或者Current。*/
    inventoryConf.setIncludedObjectVersions(InventoryIncludedObjectVersions::All);

    /* (可選)設定清單結果中應包含的配置項, 請按需配置。*/
    InventoryOptionalFields field { 
        InventoryOptionalField::Size, InventoryOptionalField::LastModifiedDate, 
        InventoryOptionalField::ETag, InventoryOptionalField::StorageClass, 
        InventoryOptionalField::IsMultipartUploaded, InventoryOptionalField::EncryptionStatus
    };
    inventoryConf.setOptionalFields(field);

    /* 設定清單配置。*/
    auto outcome = client.SetBucketInventoryConfiguration(
        SetBucketInventoryConfigurationRequest(BucketName, inventoryConf));

    if (!outcome.isSuccess()) {
        /* 異常處理。*/
        std::cout << "Set Bucket Inventory fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }

    /* 釋放網路等資源。*/
    ShutdownSdk();
    return 0;
}
package main

import (
	"context"
	"flag"
	"log"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// 定義全域變數
var (
	region     string // 儲存地區
	bucketName string // 儲存空間名稱
)

// init函數用於初始化命令列參數
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
}

func main() {
	// 解析命令列參數
	flag.Parse()

	var (
		accountId   = "account id of the bucket" // 儲存空間所有者授予的賬戶ID,例如109885487000****
		inventoryId = "inventory id"             // 由使用者指定的清單名稱,清單名稱在當前Bucket下必須全域唯一
	)

	// 檢查bucket名稱是否為空白
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 檢查region是否為空白
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 載入預設配置並設定憑證提供者和地區
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// 建立OSS用戶端
	client := oss.NewClient(cfg)

	// 建立設定儲存空間清單的請求
	putRequest := &oss.PutBucketInventoryRequest{
		Bucket:      oss.Ptr(bucketName),  // 儲存空間名稱
		InventoryId: oss.Ptr(inventoryId), // 由使用者指定的清單名稱
		InventoryConfiguration: &oss.InventoryConfiguration{
			Id:        oss.Ptr(inventoryId), // 由使用者指定的清單名稱
			IsEnabled: oss.Ptr(true),        // 啟用清單配置
			Filter: &oss.InventoryFilter{
				Prefix:                   oss.Ptr("filterPrefix"),    // 設定清單篩選規則,指定篩選Object的首碼
				LastModifyBeginTimeStamp: oss.Ptr(int64(1637883649)), // 最後修改開始時間戳
				LastModifyEndTimeStamp:   oss.Ptr(int64(1638347592)), // 最後修改結束時間戳記
				LowerSizeBound:           oss.Ptr(int64(1024)),       // 檔案大小下限(位元組)
				UpperSizeBound:           oss.Ptr(int64(1048576)),    // 檔案大小上限(位元組)
				StorageClass:             oss.Ptr("Standard,IA"),     // 儲存類型
			},
			Destination: &oss.InventoryDestination{
				OSSBucketDestination: &oss.InventoryOSSBucketDestination{
					Format:    oss.InventoryFormatCSV,                                   // 匯出資訊清單檔的檔案格式
					AccountId: oss.Ptr(accountId),                                       // 儲存空間所有者授予的賬戶ID,例如109885487000****
					RoleArn:   oss.Ptr("acs:ram::" + accountId + ":role/AliyunOSSRole"), // 儲存空間所有者授予操作許可權的角色名稱,比如acs:ram::109885487000****:role/ram-test
					Bucket:    oss.Ptr("acs:oss:::" + bucketName),                       // 存放匯出的清單結果的Bucket名稱
					Prefix:    oss.Ptr("export/"),                                       // 存放清單結果的儲存路徑首碼
				},
			},
			Schedule: &oss.InventorySchedule{
				Frequency: oss.InventoryFrequencyDaily, // 資訊清單檔匯出的周期(每天)
			},
			IncludedObjectVersions: oss.Ptr("All"), // 是否在清單中包含Object的所有版本資訊
		},
	}

	// 執行設定儲存空間清單的請求
	putResult, err := client.PutBucketInventory(context.TODO(), putRequest)
	if err != nil {
		log.Fatalf("failed to put bucket inventory %v", err)
	}

	// 列印設定儲存空間清單的結果
	log.Printf("put bucket inventory result:%#v\n", putResult)
}

ossutil

通過命令列工具進行配置,適用於指令碼化、批量化的營運操作。使用前請先安裝並配置ossutil2.0

命令格式

ossutil api put-bucket-inventory --bucket <bucket_name> --inventory-id <inventory_id> --inventory-configuration <json_config>

樣本

# 此命令為名為 examplebucket 的 Bucket 建立一個名為 daily-report 的清單規則
# 報告每日產生,儲存到 destbucket 的 reports/ 路徑下
# 需要提前配置好 ossutil 的認證資訊
ossutil api put-bucket-inventory --bucket examplebucket --inventory-id daily-report --inventory-configuration '{
    "Id": "daily-report",
    "IsEnabled": "true",
    "Destination": {
        "OSSBucketDestination": {
            "Format": "CSV",
            "AccountId": "100000000000000",

            "RoleArn": "acs:ram::100000000000000:role/oss-inventory-role",
            "Bucket": "acs:oss:::destbucket",
            "Prefix": "reports/"
        }
    },
    "Schedule": {
        "Frequency": "Daily"
    },
    "IncludedObjectVersions": "Current",
    "OptionalFields": {
        "Field": ["Size", "LastModifiedDate", "StorageClass"]
    }
}'
注意:關於 put-bucket-inventory 命令的詳細用法,請參考 put-bucket-inventory

API

以上操作方式底層基於API實現,如果對程式自訂要求較高,可以直接發起REST API請求。直接發起REST API請求需要手動編寫代碼計算簽名。

步驟三:解析清單

清單任務以非同步方式執行。清單報告的所有檔案都儲存在一個以掃描啟動時間命名的檔案夾中。核心檔案包括 manifest.jsondata/ 目錄下的 .csv.gz 資料檔案。要確認任務是否完成,可以檢查目標是否已產生 manifest.json 檔案。

第一步:讀取 manifest.json 檔案

清單報告的列順序是動態,它取決於在配置清單規則時選擇的欄位。需要先解析 manifest.json 檔案來擷取正確的列順序,然後再處理資料檔案。該檔案包含了本次清單任務的核心中繼資料。需要重點關注以下兩個欄位:

  • fileSchema: 一個字串,定義了 CSV 檔案中各列的名稱和確切順序。

  • files: 一個數組,列出了本次報告產生的所有 .csv.gz 資料檔案的詳細資料,包括其路徑(key)、大小(size)和 MD5 校正值(MD5checksum)。

manifest.json 樣本:

{
  "sourceBucket": "your-source-bucket",
  "destinationBucket": "your-destination-bucket",
  "version": "2019-09-01",
  "creationTimestamp": "1642994594",
  "fileFormat": "CSV",
  "fileSchema": "Bucket, Key, Size, LastModifiedDate, ETag, StorageClass, EncryptionStatus",
  "files": [
    {
      "key": "inventory-reports/your-source-bucket/daily-report/data/a1b2c3d4-....csv.gz",
      "size": 20480,
      "MD5checksum": "F77449179760C3B13F1E76110F07****"
    }
  ]
}

第二步:根據 fileSchema 解析 CSV 資料檔案

  1. 擷取並解壓檔案

    manifest.jsonfiles 數組中擷取每個資料檔案的 key(即檔案路徑)。根據該路徑下載對應的 .csv.gz 壓縮包。解壓檔案,得到 CSV 格式的未經處理資料。

    重要Key在 CSV 檔案中經過了 URL 編碼,在使用前需要先進行 URL 解碼。
  2. 按序解析資料

    fileSchema 欄位中定義的順序作為 CSV 檔案的欄位標題。逐行讀取解壓後的 CSV 檔案。每一行代表一個對象(檔案)的完整記錄,每一列則對應 fileSchema 中指定的一個欄位。

    CSV 內容樣本:

    假設 fileSchema 為: Bucket,Key,Size,StorageClass,LastModifiedDate。那麼對應的 CSV 內容格式如下:

    "my-source-bucket","images/photo.jpg",102400,"Standard","2023-10-26T08:00:00.000Z"
    "my-source-bucket","docs/report.pdf",2048000,"IA","2023-10-25T10:30:00.000Z"

資訊清單檔

清單任務配置完成後,OSS會按清單規則指定的匯出周期產生資訊清單檔。資訊清單檔的目錄結構如下:

<dest-bucket-name>/
└── <dest-prefix>/
    └── <source-bucket-name>/
        └── <inventory-id>/
            ├── YYYY-MM-DDTHH-MMZ/  (掃描開始的UTC時間)
            │   ├── manifest.json   (清單任務的中繼資料檔案)
            │   └── manifest.checksum (manifest.json 檔案的 MD5 校正和)
            └── data/
                └── <uuid>.csv.gz   (GZIP 壓縮的清單資料檔案)

目錄結構

說明

dest-prefix

該目錄根據設定的清單報告名首碼產生,如果清單報告名首碼設定為空白,將省略該目錄。

source-bucket-name/

該目錄根據配置清單報告的源Bucket名產生。

inventory_id/

該目錄根據清單任務的規則名稱產生。

YYYY-MM-DDTHH-MMZ/

該目錄是標準的格林威治時間戳記,表示開始掃描Bucket的時間,例如2020-05-17T16-00Z。該目錄下包含了manifest.jsonmanifest.checksum檔案。

data/

該目錄下存放了包含源Bucket中的對象列表以及每個對象的中繼資料的資訊清單檔,資訊清單檔格式為使用GZIP壓縮的CSV檔案。

重要
  • 當匯出的源Bucket中Object數量較多時,為方便使用者下載和處理資料,程式會自動將資訊清單檔切分成多個CSV壓縮檔。CSV壓縮檔按照uuid.csv.gzuuid-1.csv.gzuuid-2.csv.gz的順序依次遞增。可以從manifest.json檔案中擷取CSV檔案清單,然後按照以上順序依次解壓CSV檔案並讀取清單資料。

  • Object的單條記錄資訊僅出現在一個資訊清單檔內,不會分布到不同的資訊清單檔。

清單功能產生的具體檔案說明如下:

manifest檔案

manifest檔案包含manifest.jsonmanifest.checksum,詳細說明如下:

  • manifest.json:提供了有關清單的中繼資料和其他基本資料。

    {
        "creationTimestamp": "1642994594",
        "destinationBucket": "destbucket",
        "fileFormat": "CSV",
        "fileSchema": "Bucket, Key, VersionId, IsLatest, IsDeleteMarker, Size, StorageClass, LastModifiedDate, ETag, IsMultipartUploaded, EncryptionStatus, ObjectAcl, TaggingCount, ObjectType, Crc64",
        "files": [{
                "MD5checksum": "F77449179760C3B13F1E76110F07****",
                "key": "destprefix/srcbucket/configid/data/a1574226-b5e5-40ee-91df-356845777c04.csv.gz",
                "size": 2046}],
        "sourceBucket": "srcbucket",
        "version": "2019-09-01"
    }

    各欄位詳細說明如下:

    欄位名稱

    說明

    creationTimestamp

    以紀元日期格式建立的時間戳記,顯示開始掃描源Bucket的時間。

    destinationBucket

    存放資訊清單檔的目標Bucket。

    fileFormat

    資訊清單檔的格式。

    fileSchema

    資訊清單檔包含的欄位,分為固定欄位和可選欄位。其中,固定欄位的順序是固定的,可選欄位的排列順序取決於配置清單規則時清單內容欄位的排列順序(控制台配置時以欄位的勾選先後順序為準)。 因此,建議以fileSchema中的欄位順序去解析csv.gz中的資料列,避免出現列和屬性對應錯誤的情況。

    • 配置清單規則時如果對象版本選擇了目前的版本,則fileSchema中,先排列固定欄位Bucket, Key,後續為可選欄位。

    • 配置清單規則時如果對象版本選擇了所有版本,則fileSchema中,先排列固定欄位Bucket, Key, VersionId, IsLatest, IsDeleteMarker,後續為可選欄位。

    files

    包含資訊清單檔的MD5值、檔案名稱完整路徑及檔案大小。

    sourceBucket

    配置清單規則的源Bucket。

    version

    清單版本號碼。

  • manifest.checksum:包含manifest.json檔案的MD5值,例如8420A430CBD6B659A1C0DFC1C11A****

清單報告

清單報告儲存在data/目錄中,包含清單功能匯出的檔案資訊。清單報告樣本如下:

image

清單報告具體的欄位順序取決於配置清單規則時的清單內容欄位排列順序。以上清單報告樣本中,各欄位按從左至右的順序說明如下。

欄位名稱

說明

Bucket

執行清單任務的源Bucket名稱。

Key

Bucket中Object的名稱。

Object名稱使用URL編碼,可按需解碼。

VersionId

Object的版本ID。僅當配置的清單規則為匯出所有版本時出現此欄位。

  • 如果配置清單規則的Bucket未開啟版本控制,則該欄位顯示為空白。

  • 如果配置清單規則的Bucket已開啟版本控制,則該欄位顯示為Object的versionId。

IsLatest

Object版本是否為最新版本。僅當配置的清單規則為匯出所有版本時出現此欄位。

  • 如果配置清單規則的Bucket未開啟版本控制,則該欄位顯示為true

  • 如果配置清單規則的Bucket已開啟版本控制,且Object為最新版本時,則該欄位顯示為true。如果Object為歷史版本,則該欄位顯示為false。

IsDeleteMarker

Object版本是否為刪除標記。僅當配置的清單規則為匯出所有版本時出現此欄位。

  • 如果配置清單規則的Bucket未開啟版本控制,則該欄位預設顯示為false

  • 如果配置清單規則的Bucket已開啟版本控制,且Object為刪除標記時,則該欄位顯示為true。如果Object不是刪除標記,則該欄位顯示為false

Size

Object大小。

StorageClass

Object的儲存類型。

LastModifiedDate

Object的最後修改時間,格式是格林威治時間,與北京時間相差8小時。

ETag

Object的ETag。

Object產生時會建立相應的ETag,用於標識一個Object的內容。

  • 通過PutObject介面建立的Object,ETag值是其內容的MD5值。

  • 通過其他方式建立的Object,ETag值是基於一定計算規則產生的唯一值,但不是其內容的MD5值。

IsMultipartUploaded

Object是否通過分區上傳產生。如果是,則該欄位值為true,否則為false

EncryptionStatus

Object是否已加密。若Object已加密,則該欄位值為true,否則為false

ObjectAcl

Object的讀寫權限。更多資訊,請參見Object ACL

TaggingCount

Object的標籤個數。

ObjectType

Object類型。更多資訊,請參見Object類型

Crc64

Object的CRC64。

使用限制

  • 規則數量:單個 Bucket 最多支援 1000 條清單規則(通過 API/SDK)或 10 條(通過控制台)。

  • 地區限制:源 Bucket 和目標 Bucket 必須位於同一地區、同一阿里雲帳號下。金融雲和無地區屬性的 Bucket 不支援此功能。

計費說明

儲存空間清單功能本身免費,但會產生以下關聯費用:

  • API 請求費:配置和擷取清單規則時產生的 Put 請求費用和Get請求費用。OSS 寫入清單報告到目標 Bucket 時會產生 PUT 請求費用。下載和讀取清單報告時,會產生 GET 請求費用。

  • 儲存費用:產生的清單報告(manifest 檔案和 csv.gz 檔案)會佔用目標 Bucket 的儲存空間,按標準儲存費用計費。

  • 外網流出費用:使用外網 Endpoint 下載和讀取清單報告時,會產生外網流出流量費用。

為避免不必要的開銷,請及時刪除不再需要的清單規則,並使用生命週期規則自動清理到期的清單報告檔案。

應用於生產環境

最佳實務

  • 最小許可權:始終使用專用的、具備最小許可權的 RAM 角色,切勿在生產環境中使用 AliyunOSSRole

  • 效能建議:對於高流量的源 Bucket,應將清單報告儲存到另一個專用的 Bucket,避免因寫入報告而產生的頻寬競爭影響線上業務。

  • 成本最佳化:儲存空間清單支援按天或按周匯出資訊清單檔。對於超過百億檔案的 Bucket,優先使用每周清單。同時,在目標 Bucket 上配置生命週期規則,自動刪除超過 N 天(例如 30 天)的清單報告以節省儲存成本。

    Bucket內的檔案數量

    匯出建議

    <100億

    按需配置按天或按周匯出

    100億~500億

    按周匯出

    ≥500億

    • 按首碼匹配分批匯出

    • 通過提升匯出Bucket檔案數量的限制

  • 首碼分區:對於超大規模(如千億級)的 Bucket,可按業務首碼建立多條清單規則,分而治之地產生報告,便於管理和處理。

風險防範

  • 資料審計:匯出資訊清單檔的過程中,由於Object的建立、刪除或覆蓋等操作,可能會導致最終輸出的清單列表中不一定包含所有的Object。最後修改時間早於manifest.json檔案中createTimeStamp欄位顯示時間的Object會出現在資訊清單檔中;最後修改時間晚於createTimeStamp欄位顯示時間的Object可能不會出現在資訊清單檔中。建議對清單列表中的Object進行操作之前,先使用HeadObject介面檢查Object的屬性。

  • 監控警示:監控目標 Bucket 的儲存用量,防止資訊清單檔無限制增長導致成本失控。監控 PutBucketInventory 等 API 的調用,以便追蹤配置變更。

  • 變更管理:清單規則的變更(如修改首碼、頻率)會影響下遊的資料分析流程。所有變更應納入版本控制和評審流程。

常見問題