IBM Cloud Docs
使用 Python

使用 Python

Python 支援是透過 boto3 程式庫的分支而提供,而此程式庫具有可充分利用 IBM Cloud® Object Storage 的特性。

它可以透過 pip install ibm-cos-sdk 從 Python Package Index 進行安裝。

原始碼可在 GitHub.

ibm_boto3 程式庫提供對 IBM Cloud® Object Storage API 的完整存取。 建立服務資源或低階用戶端時必須指定端點、API 金鑰及實例 ID,如下列基本範例中所示。

服務實體 ID 也稱為_資源實體 ID_。 可以藉由建立服務認證,或透過 CLI 找到值。

詳細文件請參閱 這裡

建立用戶端及讀取認證

為了連接至 COS,將使用認證資訊(API 金鑰和服務實例 ID)來建立和配置用戶端。 這些值也可以自動從 credentials 檔案或環境變數中取得。

產生服務認證後,會將產生的 JSON 文件儲存為 ~/.bluemix/cos_credentials。 除非在建立用戶端期間,明確地設定其他認證,否則 SDK 將自動從此檔案讀取認證。 如果 cos_credentials 檔案包含 HMAC 金鑰,則用戶端會使用簽章進行鑑別,否則用戶端會使用所提供的 API 金鑰來使用載送記號進行鑑別 (使用 API 金鑰仍需要在用戶端建立期間併入 config=Config(signature_version="oauth") )。

如果從 AWS S3 移轉,您也可以使用下列格式從 ~/.aws/credentials 讀取認證資料:

[default]
aws_access_key_id = {API_KEY}
aws_secret_access_key = {SERVICE_INSTANCE_ID}

注意:如果 ~/.bluemix/cos_credentials~/.aws/credentials 都存在,則 cos_credentials 優先。

收集必要資訊

下列變數會出現在範例中:

  • bucket_name 必須是唯一且 DNS 安全的字串。 因為儲存區名稱在整個系統中是唯一的,因此如果此範例執行多次,將需要變更這些值。 請注意,名稱在刪除後會保留 10 到 15 分鐘。
  • ibm_api_key_id服務認證中作為 apikey 找到的值。
  • ibm_service_instance_id服務認證中作為 resource_instance_id 找到的值。
  • endpoint_url 是服務端點 URL,包含 https:// 通訊協定。 此值並非 服務憑證 中的 endpoints 值。 如需端點的相關資訊,請參閱端點及儲存空間位置
  • LocationConstraint 是與 值對應的 endpoint 有效佈建代碼

程式碼範例

程式碼範例在支援的 Python發行版本上進行測試。

在程式碼中,您必須移除這裡提供的角括弧或任何其他多餘字元,以作為圖解。

起始設定配置

此範例會建立 resource 物件。 資源提供 COS 的物件導向介面。 這容許比用戶端物件所提供的低階呼叫更高的抽象層次。

請注意,部分作業 (例如 Aspera 高速傳送) 需要 client 物件。 Aspera 本身需要 Python 3.6版。

舊式注意事項: Aspera 的支援被視為舊式。 請改用 Aspera Transfer SDK

import ibm_boto3
from ibm_botocore.client import Config, ClientError

# Constants for IBM COS values
COS_ENDPOINT = "<endpoint>" # Current list avaiable at https://control.cloud-object-storage.cloud.ibm.com/v2/endpoints
COS_API_KEY_ID = "<api-key>" # eg "W00YixxxxxxxxxxMB-odB-2ySfTrFBIQQWanc--P3byk"
COS_INSTANCE_CRN = "<service-instance-id>" # eg "crn:v1:bluemix:public:cloud-object-storage:global:a/3bf0d9003xxxxxxxxxx1c3e97696b71c:d6f04d83-6c4f-4a62-a165-696756d63903::"

# Create resource
cos_resource = ibm_boto3.resource("s3",
    ibm_api_key_id=COS_API_KEY_ID,
    ibm_service_instance_id=COS_INSTANCE_CRN,
    config=Config(signature_version="oauth"),
    endpoint_url=COS_ENDPOINT
)

用戶端提供 COS S3 API 的低階介面。 這允許直接處理 HTTP 回應,而不是利用資源提供的抽象方法和屬性來存取標頭或 XML 回應有效負載所包含的資訊。


import ibm_boto3
from ibm_botocore.client import Config, ClientError

# Constants for IBM COS values
COS_ENDPOINT = "<endpoint>" # Current list avaiable at https://control.cloud-object-storage.cloud.ibm.com/v2/endpoints
COS_API_KEY_ID = "<api-key>" # eg "W00YixxxxxxxxxxMB-odB-2ySfTrFBIQQWanc--P3byk"
COS_INSTANCE_CRN = "<service-instance-id>" # eg "crn:v1:bluemix:public:cloud-object-storage:global:a/3bf0d9003xxxxxxxxxx1c3e97696b71c:d6f04d83-6c4f-4a62-a165-696756d63903::"

# Create client
cos_client = ibm_boto3.client("s3",
    ibm_api_key_id=COS_API_KEY_ID,
    ibm_service_instance_id=COS_INSTANCE_CRN,
    config=Config(signature_version="oauth"),
    endpoint_url=COS_ENDPOINT
)

金鑰值

  • <endpoint>- 您的雲端 Object Storage 的公共端點,模式前綴為 (' https:// ') (可從 IBM Cloud Dashboard 取得)。 如需端點的相關資訊,請參閱端點及儲存空間位置
  • <api-key>- 建立服務憑證時產生的 api 金鑰 (建立和刪除範例需要寫入存取權限)
  • <service-instance-id>- 雲端 Object Storage 的資源 ID (可透過 IBM Cloud CLIIBM Cloud Dashboard 取得)
  • <location>- 您的雲端 Object Storage 的預設位置 (必須與 <endpoint> 使用的區域相符 )

SDK 參照

建立新的儲存區

下面的範例使用低層次介面的用戶端。

LocationConstraint 的有效佈建碼清單可以在儲存空間類別手冊中參閱。

def create_bucket(bucket_name):
    print("Creating new bucket: {0}".format(bucket_name))
    try:
        cos_client.create_bucket(
            Bucket=bucket_name,
            CreateBucketConfiguration={
                "LocationConstraint":COS_BUCKET_LOCATION
            }
        )
        print("Bucket: {0} created!".format(bucket_name))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to create bucket: {0}".format(e))

SDK 參照

方法

建立新的文字檔

def create_text_file(bucket_name, item_name, file_text):
    print("Creating new item: {0}".format(item_name))
    try:
        cos_client.put_object(
            Bucket=bucket_name,
            Key=item_name,
            Body=file_text
        )
        print("Item: {0} created!".format(item_name))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to create text file: {0}".format(e))

SDK 參照

方法

列出可用的儲存區

def get_buckets():
    print("Retrieving list of buckets")
    try:
        buckets = cos_client.list_buckets()
        for bucket in buckets["Buckets"]:
            print("Bucket Name: {0}".format(bucket["Name"]))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to retrieve list buckets: {0}".format(e))

SDK 參照

方法

列出儲存區中的項目

def get_bucket_contents(bucket_name):
    print("Retrieving bucket contents from: {0}".format(bucket_name))
    try:
        files = cos_client.list_objects(Bucket=bucket_name)
        for file in files.get("Contents", []):
            print("Item: {0} ({1} bytes).".format(file["Key"], file["Size"]))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to retrieve bucket contents: {0}".format(e))

SDK 參照

方法

取得特定項目的檔案內容

def get_item(bucket_name, item_name):
    print("Retrieving item from bucket: {0}, key: {1}".format(bucket_name, item_name))
    try:
        file = cos_client.get_object(Bucket=bucket_name, Key=item_name)
        print("File Contents: {0}".format(file["Body"].read()))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to retrieve file contents: {0}".format(e))

SDK 參照

方法

從儲存區刪除項目

def delete_item(bucket_name, object_name):
    try:
        cos_client.delete_object(Bucket=bucket_name, Key=object_name)
        print("Item: {0} deleted!\n".format(object_name))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to delete object: {0}".format(e))

SDK 參照

方法

從儲存區刪除多個項目

刪除要求最多可以包含您要刪除的 1000 個金鑰。 雖然這對於降低每次要求的效能衝擊很有用,但在刪除許多鍵時要小心。 此外,也請考量物件的大小,以確保適當的效能。

def delete_items(bucket_name):
    try:
        delete_request = {
            "Objects": [
                { "Key": "deletetest/testfile1.txt" },
                { "Key": "deletetest/testfile2.txt" },
                { "Key": "deletetest/testfile3.txt" },
                { "Key": "deletetest/testfile4.txt" },
                { "Key": "deletetest/testfile5.txt" }
            ]
        }

        response = cos_client.delete_objects(
            Bucket=bucket_name,
            Delete=delete_request
        )

        print("Deleted items for {0}\n".format(bucket_name))
        print(json.dumps(response.get("Deleted"), indent=4))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to copy item: {0}".format(e))

SDK 參照

方法

刪除儲存區

def delete_bucket(bucket_name):
    print("Deleting bucket: {0}".format(bucket_name))
    try:
        cos_client.delete_bucket(Bucket=bucket_name)
        print("Bucket: {0} deleted!".format(bucket_name))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to delete bucket: {0}".format(e))

SDK 參照

方法

刪除後,水桶名稱會保留 10 - 15 分鐘。

執行多部分上傳

上傳二進位檔(偏好的方法)

upload_fileobjS3 物件的方法,必要時會自動執行多部分上傳。 該 TransferConfig 類別用來決定使用多部分上傳的臨界值。

def multi_part_upload(bucket_name, item_name, file_path):
    try:
        print("Starting file transfer for {0} to bucket: {1}\n".format(item_name, bucket_name))
        # set 5 MB chunks
        part_size = 1024 * 1024 * 5

        # set threadhold to 15 MB
        file_threshold = 1024 * 1024 * 15

        # set the transfer threshold and chunk size
        transfer_config = ibm_boto3.s3.transfer.TransferConfig(
            multipart_threshold=file_threshold,
            multipart_chunksize=part_size
        )

        # the upload_fileobj method will automatically execute a multi-part upload
        # in 5 MB chunks for all files over 15 MB
        with open(file_path, "rb") as file_data:
            cos_client.upload_fileobj(
                Bucket=bucket_name,
                Key=item_name,
                Fileobj=file_data,
                Config=transfer_config
            )

        print("Transfer for {0} Complete!\n".format(item_name))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to complete multi-part upload: {0}".format(e))

SDK 參照

方法

手動執行多部分上傳

如果需要,該 S3.Client 類別可用於執行多部分上傳。 這適用於需要對上傳處理程序有更多控制權的情況。

def multi_part_upload_manual(bucket_name, item_name, file_path):
    try:
        # create client object
        cos_client = ibm_boto3.client("s3",
            ibm_api_key_id=COS_API_KEY_ID,
            ibm_service_instance_id=COS_SERVICE_CRN,
            config=Config(signature_version="oauth"),
            endpoint_url=COS_ENDPOINT
        )

        print("Starting multi-part upload for {0} to bucket: {1}\n".format(item_name, bucket_name))

        # initiate the multi-part upload
        mp = cos_client.create_multipart_upload(
            Bucket=bucket_name,
            Key=item_name
        )

        upload_id = mp["UploadId"]

        # min 20MB part size
        part_size = 1024 * 1024 * 20
        file_size = os.stat(file_path).st_size
        part_count = int(math.ceil(file_size / float(part_size)))
        data_packs = []
        position = 0
        part_num = 0

        # begin uploading the parts
        with open(file_path, "rb") as file:
            for i in range(part_count):
                part_num = i + 1
                part_size = min(part_size, (file_size - position))

                print("Uploading to {0} (part {1} of {2})".format(item_name, part_num, part_count))

                file_data = file.read(part_size)

                mp_part = cos_client.upload_part(
                    Bucket=bucket_name,
                    Key=item_name,
                    PartNumber=part_num,
                    Body=file_data,
                    ContentLength=part_size,
                    UploadId=upload_id
                )

                data_packs.append({
                    "ETag":mp_part["ETag"],
                    "PartNumber":part_num
                })

                position += part_size

        # complete upload
        cos_client.complete_multipart_upload(
            Bucket=bucket_name,
            Key=item_name,
            UploadId=upload_id,
            MultipartUpload={
                "Parts": data_packs
            }
        )
        print("Upload for {0} Complete!\n".format(item_name))
    except ClientError as be:
        # abort the upload
        cos_client.abort_multipart_upload(
            Bucket=bucket_name,
            Key=item_name,
            UploadId=upload_id
        )
        print("Multi-part upload aborted for {0}\n".format(item_name))
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to complete multi-part upload: {0}".format(e))

SDK 參照已繼續

類別

方法

使用 TransferManager 的大型物件上傳

TransferManager 提供另一種方式來執行大型檔案傳送,方法是在必須設定配置參數時自動併入多部分上傳。

def upload_large_file(bucket_name, item_name, file_path):
    print("Starting large file upload for {0} to bucket: {1}".format(item_name, bucket_name))

    # set the chunk size to 5 MB
    part_size = 1024 * 1024 * 5

    # set threadhold to 5 MB
    file_threshold = 1024 * 1024 * 5

    # Create client connection
    cos_client = ibm_boto3.client("s3",
        ibm_api_key_id=COS_API_KEY_ID,
        ibm_service_instance_id=COS_SERVICE_CRN,
        config=Config(signature_version="oauth"),
        endpoint_url=COS_ENDPOINT
    )

    # set the transfer threshold and chunk size in config settings
    transfer_config = ibm_boto3.s3.transfer.TransferConfig(
        multipart_threshold=file_threshold,
        multipart_chunksize=part_size
    )

    # create transfer manager
    transfer_mgr = ibm_boto3.s3.transfer.TransferManager(cos_client, config=transfer_config)

    try:
        # initiate file upload
        future = transfer_mgr.upload(file_path, bucket_name, item_name)

        # wait for upload to complete
        future.result()

        print ("Large file upload complete!")
    except Exception as e:
        print("Unable to complete large file upload: {0}".format(e))
    finally:
        transfer_mgr.shutdown()

列出儲存區中的項目(第 2 版)

S3.Client 物件具有已更新的方法來列出內容 (list_objects_v2)。 此方法可讓您限制傳回的記錄數,並分批次擷取記錄。 這可能有助於在應用程式內將您的結果進行分頁,並改善效能。

def get_bucket_contents_v2(bucket_name, max_keys):
    print("Retrieving bucket contents from: {0}".format(bucket_name))
    try:
        # create client object
        cos_client = ibm_boto3.client("s3",
            ibm_api_key_id=COS_API_KEY_ID,
            ibm_service_instance_id=COS_SERVICE_CRN,
            config=Config(signature_version="oauth"),
            endpoint_url=COS_ENDPOINT)

        more_results = True
        next_token = ""

        while (more_results):
            response = cos_client.list_objects_v2(Bucket=bucket_name, MaxKeys=max_keys, ContinuationToken=next_token)
            files = response["Contents"]
            for file in files:
                print("Item: {0} ({1} bytes).".format(file["Key"], file["Size"]))

            if (response["IsTruncated"]):
                next_token = response["NextContinuationToken"]
                print("...More results in next batch!\n")
            else:
                more_results = False
                next_token = ""

    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to retrieve bucket contents: {0}".format(e))

SDK 參照

方法

使用 Key Protect

Key Protect 可新增至儲存空間儲存區,以加密雲端中靜止的機密資料。

開始之前

為了建立儲存區並啟用 Key Protect,需要下列項目:

擷取根金鑰 CRN

  1. 擷取 Key Protect 服務的實例 ID
  2. 使用 Key Protect API 來擷取所有可用金鑰
  3. 擷取您用來在儲存區上啟用 Key Protect 的根金鑰 CRN。 CRN 看起來如下:

crn:v1:bluemix:public:kms:us-south:a/3d624cd74a0dea86ed8efe3101341742:90b6a1db-0fe1-4fe9-b91e-962c327df531:key:0bg3e33e-a866-50f2-b715-5cba2bc93234

建立儲存區並啟用 key-protect

COS_KP_ALGORITHM = "<algorithm>"
COS_KP_ROOTKEY_CRN = "<root-key-crn>"

# Create a new bucket with key protect (encryption)
def create_bucket_kp(bucket_name):
    print("Creating new encrypted bucket: {0}".format(bucket_name))
    try:
        cos_client.create_bucket(
            Bucket=bucket_name,
            CreateBucketConfiguration={
                "LocationConstraint":COS_BUCKET_LOCATION
            },
            IBMSSEKPEncryptionAlgorithm=COS_KP_ALGORITHM,
            IBMSSEKPCustomerRootKeyCrn=COS_KP_ROOTKEY_CRN
        )
        print("Encrypted Bucket: {0} created!".format(bucket_name))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to create encrypted bucket: {0}".format(e))

金鑰值

  • <algorithm>- 新增到儲存桶的新物件所使用的加密算法 (預設為 AES256 )。
  • <root-key-crn>- 從 Key Protect 服務取得的 Root Key 的 CRN。

SDK 參照

方法

使用 Aspera 高速傳輸

舊式注意事項: Aspera 的支援被視為舊式。 建議使用者使用 Aspera Transfer SDK[https://developer.ibm.com/apis/catalog/aspera--aspera-transfer-sdk/API Reference]。

舊式注意事項: Aspera 的支援被視為舊式。 建議使用者使用 Aspera Transfer SDK

透過安裝 Aspera 高速傳送程式庫,您可以在應用程式中使用高速檔案傳送。 Aspera 程式庫是封閉的來源,因此對於 COS SDK(其使用 Apache 授權)具有選用的相依關係。

每一個 Aspera 階段作業都會建立在用戶端機器上執行的個別 ascp 處理程序,以執行傳送。 請確定您的運算環境可以容許執行此處理程序。

起始設定 AsperaTransferManager

在初始化 AsperaTransferManager 之前,請確認您有一個可運作的 client (不是 resourcesession) 物件。

import ibm_boto3
from ibm_botocore.client import Config
from ibm_s3transfer.aspera.manager import AsperaTransferManager

COS_ENDPOINT = "<endpoint>" # Current list avaiable at https://control.cloud-object-storage.cloud.ibm.com/v2/endpoints
COS_API_KEY_ID = "<api-key>"
COS_RESOURCE_CRN = "<resource-instance-id>"
COS_BUCKET_LOCATION = "<location>"

# Create resource
cos_client = ibm_boto3.client("s3",
    ibm_api_key_id=COS_API_KEY_ID,
    ibm_service_instance_id=COS_RESOURCE_CRN,
    config=Config(signature_version="oauth"),
    endpoint_url=COS_ENDPOINT
)

transfer_manager = AsperaTransferManager(cos)

您需要提供 IAM API 金鑰,以進行 Aspera 高速傳送。 目前 支援 HMAC 認證。 如需 IAM 的相關資訊,請按一下這裡

為了得到最高的傳輸量,請將傳送分割成指定數目的平行階段作業 ,以傳送大小由 threshold 值定義的資料區塊。

使用多個階段作業的一般配置應該是:

  • 2500 MBps 目標率
  • 100 MB 臨界值(此為大部分應用程式的建議值
ms_transfer_config = AsperaConfig(multi_session="all",
                                  target_rate_mbps=2500,
                                  multi_session_threshold_mb=100)

在上述範例中,SDK 會大量產生足夠的階段作業,以嘗試達到目標率 2500 MBps。

也可以在 SDK 中明確配置階段作業管理。 在想要更精確控制網路使用率的情況下,這十分有用。

使用明確的多個階段作業的一般配置應該是:

  • 2 或 10 個階段作業
  • 100 MB 臨界值(此為大部分應用程式的建議值
from ibm_s3transfer.aspera.manager import AsperaConfig
# Configure 2 sessions for transfer
ms_transfer_config = AsperaConfig(multi_session=2,
                                  multi_session_threshold_mb=100)

# Create the Aspera Transfer Manager
transfer_manager = AsperaTransferManager(client=client,
                                         transfer_config=ms_transfer_config)

為了在大多數情況下獲得最佳效能,請務必使用多個階段,以盡量減少任何與實體化 Aspera 高速傳輸相關的處理。 如果您的網路容量至少為 1 Gbps,您應該使用 10 個階段作業。 較低頻寬的網路應該使用兩個階段作業。

檔案上傳

bucket_name = "<bucket-name>"
upload_filename = "<absolute-path-to-file>"
object_name = "<item-name>"

# Create Transfer manager
with AsperaTransferManager(client) as transfer_manager:

    # Perform upload
    future = transfer_manager.upload(upload_filename, bucket_name, object_name)

    # Wait for upload to complete
    future.result()

金鑰值

  • <bucket-name>- 目標水桶的名稱
  • <absolute-path-to-file>- 要上傳的檔案的目錄路徑和檔案名稱
  • <item-name>- 新增至儲存桶的檔案名稱

檔案下載

bucket_name = "<bucket-name>"
download_filename = "<absolute-path-to-file>"
object_name = "<object-to-download>"

# Create Transfer manager
with AsperaTransferManager(client) as transfer_manager:

    # Get object with Aspera
    future = transfer_manager.download(bucket_name, object_name, download_filename)

    # Wait for download to complete
    future.result()

金鑰值

  • <bucket-name>- Object Storage 服務實例中已啟用 Aspera 的儲存桶名稱。
  • <absolute-path-to-file>- 將檔案儲存至本機系統的目錄和檔案名稱。
  • <object-to-download>- 要下載的儲存桶中檔案的名稱。

目錄上傳

bucket_name = "<bucket-name>"
# THIS DIRECTORY MUST EXIST LOCALLY, and have objects in it.
local_upload_directory = "<absolute-path-to-directory>"
# THIS SHOULD NOT HAVE A LEADING "/"
remote_directory = "<object prefix>"

# Create Transfer manager
with AsperaTransferManager(client) as transfer_manager:

    # Perform upload
    future = transfer_manager.upload_directory(local_upload_directory, bucket_name, remote_directory)

    # Wait for upload to complete
    future.result()

金鑰值

  • <bucket-name>- Object Storage 服務實例中已啟用 Aspera 的儲存桶名稱
  • <absolute-path-to-directory>- 包含要上傳的檔案的本機目錄。 必須具有前導和尾端 /(例如,/Users/testuser/Documents/Upload/
  • <object prefix>- 儲存檔案的儲存桶中目錄的名稱。 不得具有前導斜線 /(例如,newuploads/

目錄下載

bucket_name = "<bucket-name>"
# THIS DIRECTORY MUST EXIST LOCALLY
local_download_directory = "<absolute-path-to-directory>"
remote_directory = "<object prefix>"

# Create Transfer manager
with AsperaTransferManager(client) as transfer_manager:

    # Get object with Aspera
    future = transfer_manager.download_directory(bucket_name, remote_directory, local_download_directory)

    # Wait for download to complete
    future.result()

金鑰值

  • <bucket-name>- Object Storage 服務實例中已啟用 Aspera 的儲存桶名稱
  • <absolute-path-to-directory>- 保存下載檔案的本機目錄。 必須有前斜線和後斜線 / (即 /Users/testuser/Downloads/)
  • <object prefix>- 儲存檔案的儲存桶中目錄的名稱。 不得具有前導斜線 /(例如,todownload/

使用訂閱者

訂閱者藉由連接自訂回呼方法而提供對於傳送的觀察。 所有傳送會在下列階段之間轉移:

Queued - In Progress - Done

每個階段有三個可用的訂閱者:

  • CallbackOnQueued() - 有新的傳送新增至 AsperaTransferManager 時呼叫
  • CallbackOnProgress() - 傳送已傳輸資料時呼叫(傳送進行中時會反覆地發動)。
  • CallbackOnDone() - 傳送完成之後呼叫
bucket_name = "<bucket-name>"
local_download_directory = "<absolute-path-to-directory>"
remote_directory = "<object prefix>"

# Subscriber callbacks
class CallbackOnQueued(AsperaBaseSubscriber):
    def __init__(self):
        pass

    def on_queued(self, future, **kwargs):
        print("Directory download queued.")

class CallbackOnProgress(AsperaBaseSubscriber):
    def __init__(self):
        pass

    def on_progress(self, future, bytes_transferred, **kwargs):
        print("Directory download in progress: %s bytes transferred" % bytes_transferred)

class CallbackOnDone(AsperaBaseSubscriber):
    def __init__(self):
        pass

    def on_done(self, future, **kwargs):
        print("Downloads complete!")

# Create Transfer manager
transfer_manager = AsperaTransferManager(client)

# Attach subscribers
subscribers = [CallbackOnQueued(), CallbackOnProgress(), CallbackOnDone()]

# Get object with Aspera
future = transfer_manager.download_directory(bucket_name, remote_directory, local_download_directory, None, subscribers)

# Wait for download to complete
future.result()

金鑰值

  • <bucket-name>- Object Storage 服務實例中已啟用 Aspera 的儲存桶名稱
  • <absolute-path-to-directory>- 保存下載檔案的本機目錄。 必須具有前導和尾端斜線 /(例如,/Users/testuser/Downloads/
  • <object prefix>- 儲存檔案的儲存桶中目錄的名稱。 不得具有前導斜線 /(例如,todownload/

上面的範例程式碼會產生下列輸出:

Directory download queued.
Directory download in progress: 5632 bytes transferred
Directory download in progress: 1047552 bytes transferred
...
Directory download in progress: 53295130 bytes transferred
Directory download in progress: 62106855 bytes transferred
Download complete!

暫停/繼續/取消

SDK 可讓您透過 AsperaTransferFuture 物件的下列方法來管理檔案/目錄傳送的進度:

  • pause()
  • resume()
  • cancel()

呼叫上述任一種方法時,不會產生任何副作用。 SDK 會處理適當的清除及整理。

# Create Transfer manager
bucket_name = "<bucket-name>"
local_download_directory = "<absolute-path-to-directory>"
remote_directory = "<object prefix>"

with AsperaTransferManager(client) as transfer_manager:

    # download a directory with Aspera
    future = transfer_manager.download_directory(bucket_name, remote_directory, local_download_directory, None, None)

    # pause the transfer
    future.pause()

    # resume the transfer
    future.resume()

    # cancel the transfer
    future.cancel()

疑難排解 Aspera 問題

問題: 除了 3.6 之外,使用任何 Python 版本的開發人員在安裝或使用 Aspera SDK時可能會遇到失敗。

原因: 如果您的環境中安裝了不同版本的 Python,那麼您在嘗試安裝 Aspera SDK 時可能會遇到安裝失敗的情況。 這可能是遺漏 DLL 檔案或路徑中有錯誤的 DLL 所致。

**解決方案:**解決此問題的首要步驟是重新安裝 Aspera 程式庫。 安裝期間可能有失敗。 因此,這可能已影響 DLL 檔案。 如果那未解決問題,則您必須更新 Python 的版本。 如果您無法這樣做,則可以使用安裝 Intel® Distribution for Python *。 這應該可讓您在 Python 3.6.x 上安裝 Aspera SDK,而不會有任何問題。

更新 meta 資料

有兩種方式可更新現有物件上的 meta 資料:

  • 具有新 meta 資料及原始物件內容的 PUT 要求
  • 使用將原始物件指定為複製來源的新 meta 資料來執行 COPY 要求

使用 PUT 更新 meta 資料

注意: PUT 請求會覆蓋物件的現有內容,因此必須先下載,然後再以新的元資料重新上傳。

def update_metadata_put(bucket_name, item_name, key, value):
    try:
        # retrieve the existing item to reload the contents
        response = cos_client.get_object(Bucket=bucket_name, Key=item_name)
        existing_body = response.get("Body").read()

        # set the new metadata
        new_metadata = {
            key: value
        }

        cos_client.put_object(Bucket=bucket_name, Key=item_name, Body=existing_body, Metadata=new_metadata)

        print("Metadata update (PUT) for {0} Complete!\n".format(item_name))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        log_error("Unable to update metadata: {0}".format(e))

使用 COPY 更新 meta 資料

def update_metadata_copy(bucket_name, item_name, key, value):
    try:
        # set the new metadata
        new_metadata = {
            key: value
        }

        # set the copy source to itself
        copy_source = {
            "Bucket": bucket_name,
            "Key": item_name
        }

        cos_client.copy_object(Bucket=bucket_name, Key=item_name, CopySource=copy_source, Metadata=new_metadata, MetadataDirective="REPLACE")

        print("Metadata update (COPY) for {0} Complete!\n".format(item_name))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        log_error("Unable to update metadata: {0}".format(e))

使用 Immutable Object Storage

將保護配置新增至現有儲存區

在保護期間過期,並移除物件上的所有合法保留之前,無法刪除寫入受保護儲存區的物件。 除非在建立物件時提供物件特定值,否則會將儲存區的預設保留值提供給物件。 不再保留的受保護儲存區物件(保留期間已過期,而物件沒有任何合法保留),在被改寫時會再次保留。 新的保留期間可以提供為物件改寫要求的一部分,否則會將儲存區的預設保留時間提供給物件。

保留期間設定 MinimumRetentionDefaultRetentionMaximumRetention 的最小及最大支援值為 0 天及 365243 天 (1000 年)。

def add_protection_configuration_to_bucket(bucket_name):
    try:
        new_protection_config = {
            "Status": "Retention",
            "MinimumRetention": {"Days": 10},
            "DefaultRetention": {"Days": 100},
            "MaximumRetention": {"Days": 1000}
        }

        cos_client.put_bucket_protection_configuration(Bucket=bucket_name, ProtectionConfiguration=new_protection_config)

        print("Protection added to bucket {0}\n".format(bucket_name))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to set bucket protection config: {0}".format(e))

檢查儲存區的保護

def get_protection_configuration_on_bucket(bucket_name):
    try:
        response = cos_client.get_bucket_protection_configuration(Bucket=bucket_name)
        protection_config = response.get("ProtectionConfiguration")

        print("Bucket protection config for {0}\n".format(bucket_name))
        print(protection_config)
        print("\n")
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to get bucket protection config: {0}".format(e))

上傳受保護物件

不再保留的受保護儲存區物件(保留期間已過期,而物件沒有任何合法保留),在被改寫時會再次保留。 新的保留期間可以提供為物件改寫要求的一部分,否則會將儲存區的預設保留時間提供給物件。

類型 說明
Retention-Period 非負整數(秒) 儲存在物件上的保留期間(以秒為單位)。 除非已過保留期間中指定的時間量,否則無法改寫、也不能刪除物件。 如果指定此欄位及 Retention-Expiration-Date,則會傳回 400 錯誤。 如果未指定任一項,則會使用儲存區的 DefaultRetention 期間。 零 (0) 是合法值,假設儲存區最小保留期間也為 0
Retention-expiration-date 日期(ISO 8601 格式) 在此日期將可以合法刪除或修改物件。 您只能指定此項或 Retention-Period 標頭。 如果兩者都指定,則會傳回 400 錯誤。 如果未指定任一項,則會使用儲存區的 DefaultRetention 期間。
Retention-legal-hold-id 字串 要套用至物件的單一合法保留。 合法保留是 Y 字元長字串。 除非已移除與物件相關聯的所有合法保留,否則無法改寫或刪除物件。
def put_object_add_legal_hold(bucket_name, object_name, file_text, legal_hold_id):
    print("Add legal hold {0} to {1} in bucket {2} with a putObject operation.\n".format(legal_hold_id, object_name, bucket_name))
    cos_client.put_object(
        Bucket=bucket_name,
        Key=object_name,
        Body=file_text,
        RetentionLegalHoldId=legal_hold_id)
    print("Legal hold {0} added to object {1} in bucket {2}\n".format(legal_hold_id, object_name, bucket_name))

def copy_protected_object(source_bucket_name, source_object_name, destination_bucket_name, new_object_name):
    print("Copy protected object {0} from bucket {1} to {2}/{3}.\n".format(source_object_name, source_bucket_name, destination_bucket_name, new_object_name))

    copy_source = {
        "Bucket": source_bucket_name,
        "Key": source_object_name
    }

    cos_client.copy_object(
        Bucket=destination_bucket_name,
        Key=new_object_name,
        CopySource=copy_source,
        RetentionDirective="Copy"
    )

    print("Protected object copied from {0}/{1} to {2}/{3}\n".format(source_bucket_name, source_object_name, destination_bucket_name, new_object_name));

def complete_multipart_upload_with_retention(bucket_name, object_name, upload_id, retention_period):
    print("Completing multi-part upload for object {0} in bucket {1}\n".format(object_name, bucket_name))
    cos_client.complete_multipart_upload(
        Bucket=bucket_name,
        Key=object_name,
        MultipartUpload={
            "Parts":[{
                "ETag": part["ETag"],
                "PartNumber": 1
            }]
        },
        UploadId=upload_id,
        RetentionPeriod=retention_period
    )

    print("Multi-part upload completed for object {0} in bucket {1}\n".format(object_name, bucket_name))

def upload_file_with_retention(bucket_name, object_name, path_to_file, retention_period):
    print("Uploading file {0} to object {1} in bucket {2}\n".format(path_to_file, object_name, bucket_name))

    args = {
        "RetentionPeriod": retention_period
    }

    cos_client.upload_file(
        Filename=path_to_file,
        Bucket=bucket_name,
        Key=object_name,
        ExtraArgs=args
    )

    print("File upload complete to object {0} in bucket {1}\n".format(object_name, bucket_name))

延長受保護物件的保留期間

只能延長物件的保留期間。 不能從目前配置的值縮短。

保留擴充值以三種方式之一來設定:

  • 現行值再加上時間(Additional-Retention-Period 或類似方法)
  • 新擴充期間(以秒為單位)(Extend-Retention-From-Current-Time 或類似方法)
  • 物件的新保留到期日(New-Retention-Expiration-Date 或類似方法)

物件 meta 資料中所儲存的現行保留期間可透過給定的其他時間增加,或取代為新值,視 extendRetention 要求中所設定的參數而定。 在所有情況下,會針對現行保留期間檢查延長保留參數,而且只有在更新的保留期間大於現行保留期間時,才會接受延長的參數。

不再保留的受保護儲存區物件(保留期間已過期,而物件沒有任何合法保留),在被改寫時會再次保留。 新的保留期間可以提供為物件改寫要求的一部分,否則會將儲存區的預設保留時間提供給物件。

def extend_retention_period_on_object(bucket_name, object_name, additional_seconds):
    print("Extend the retention period on {0} in bucket {1} by {2} seconds.\n".format(object_name, bucket_name, additional_seconds))

    cos_client.extend_object_retention(
        Bucket=bucket_ame,
        Key=object_name,
        AdditionalRetentionPeriod=additional_seconds
    )

    print("New retention period on {0} is {1}\n".format(object_name, additional_seconds))

列出受保護物件的合法保留

此作業傳回:

  • 物件建立日期
  • 物件保留期間(秒)
  • 根據期間和建立日期計算的保留到期日
  • 合法保留的清單
  • 合法保留 ID
  • 套用合法保留時的時間戳記

如果物件沒有任何合法保留,則會傳回空的 LegalHoldSet。 如果在物件上未指定保留期間,則會傳回 404 錯誤。

def list_legal_holds_on_object(bucket_name, object_name):
    print("List all legal holds on object {0} in bucket {1}\n".format(object_name, bucket_name));

    response = cos_client.list_legal_holds(
        Bucket=bucket_name,
        Key=object_name
    )

    print("Legal holds on bucket {0}: {1}\n".format(bucket_name, response))

建立代管的靜態網站

這項作業需要許可權,因為通常只允許儲存區擁有者配置儲存區來管理靜態網站。 這些參數決定網站訪客的預設字尾,以及選用的錯誤文件。

def putBucketWebsiteConfiguration(bucket_name):
    website_defaults = {
        'ErrorDocument': {'Key': 'error.html'},
        'IndexDocument': {'Suffix': 'index.html'},
    }
    cos_client.put_bucket_website(Bucket=bucket_name, WebsiteConfiguration=website_defaults)
    print("Website configuration set on bucket {0}\n".format(bucket_name))

後續步驟

如需相關資訊,您可以在 GitHub找到原始碼。