IBM Cloud Docs
Python 사용

Python 사용

Python 지원은 IBM Cloud® Object Storage를 최대한 활용하는 기능이 있는 boto3 라이브러리의 분기를 통해 제공됩니다.

이는 pip install ibm-cos-sdk를 통해 Python Package Index로부터 설치할 수 있습니다.

소스 코드는 다음에서 찾을 수 있습니다 GitHub.

ibm_boto3 라이브러리는 IBM Cloud® Object Storage API에 대한 완전한 액세스를 제공합니다. 다음 기본 예에 표시되어 있는 바와 같이 서비스 리소스 또는 하위 레벨 클라이언트의 작성 중에는 엔드포인트, API 키 및 인스턴스 ID를 반드시 지정해야 합니다.

서비스 인스턴스 ID는 리소스 인스턴스 ID라고도 합니다. 해당 값은 서비스 인증 정보를 작성하여 찾거나 CLI를 통해 찾을 수 있습니다.

자세한 문서는 여기에서 확인할 수 있습니다.

클라이언트 작성 및 인증 정보 제공

COS에 연결하기 위해 인증 정보(API 키 및 서비스 인스턴스 ID)를 사용하여 클라이언트가 작성되고 구성됩니다. 이러한 값은 인증 정보 파일 또는 환경 변수로부터 자동으로 가져올 수도 있습니다.

서비스 인증 정보를 생성하고 나면 결과 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 가 우선합니다.

필수 정보 수집

이 예에는 다음 변수가 있습니다.

코드 예

코드 예제는 지원되는 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에 대한 하위 레벨 인터페이스를 제공합니다. 이를 통해 리소스에서 제공하는 추상화된 메서드 및 속성을 사용하여 헤더 또는 XML 응답 페이로드에 포함된 정보에 액세스하는 대신 HTTP 응답을 직접 처리할 수 있습니다.


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>- 스키마 접두사(' https:// ')가 붙은 클라우드용 공용 엔드포인트 Object Storage ( IBM Cloud 대시보드에서 사용 가능). 엔드포인트에 대한 자세한 정보는 엔드포인트 및 스토리지 위치를 참조하십시오.
  • <api-key>- 서비스 자격 증명 생성 시 생성된 API 키(생성 및 삭제 예제에는 쓰기 권한이 필요함)
  • <service-instance-id>- 클라우드의 리소스 ID Object Storage ( IBM Cloud CLI 또는 IBM Cloud 대시보드를 통해 사용 가능)
  • <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분 동안 예약됩니다.

다중 파트 업로드 실행

2진 파일 업로드(선호되는 방법)

객체의 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()

버킷에 있는 항목 나열(v2)

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를 사용하여 사용 가능한 키를 모두 검색하십시오.
    • curl 명령을 사용하거나 Postman과 같은 API REST 클라이언트를 사용하여 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 서비스에서 얻은 루트 키의 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 ( resource 또는 session) 객체가 있는지 확인합니다.

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)

Aspera 고속 전송을 위해서는 IAM API 키를 제공해야 합니다. HMAC 신임 정보 는 현재 지원되지 않습니다. IAM에 대한 자세한 정보를 보려면 여기를 클릭하십시오.

처리량을 최고로 높이려면 임계값 값으로 크기가 정의된 데이터 청크를 전송하는 병렬 세션의 지정된 수만큼 전송을 분할하십시오.

다중 세션 사용에 대한 일반적인 구성은 다음과 같습니다.

  • 2500MBps의 목표 속도
  • 100MB의 임계값(이는 대부분의 애플리케이션에 대해 권장되는 값임)
ms_transfer_config = AsperaConfig(multi_session="all",
                                  target_rate_mbps=2500,
                                  multi_session_threshold_mb=100)

위 예에서 이 SDK는 목표 속도인 2500Mbps에 도달하기 위해 충분한 세션을 생성합니다.

SDK에서 세션 관리를 명시적으로 구성할 수도 있습니다. 이는 네트워크 이용을 더 정확하게 제어해야 하는 경우 유용합니다.

명시적 다중 세션 사용에 대한 일반적인 구성은 다음과 같습니다.

  • 2개 또는 10개의 세션
  • 100MB의 임계값(이는 대부분의 애플리케이션에 대해 권장되는 값임)
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 고속 전송 인스턴스화와 관련된 모든 처리를 최소화하세요. 네트워크 용량이 1Gbps 이상인 경우에는 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>- Aspera 을 활성화한 Object Storage 서비스 인스턴스에서 버킷의 이름입니다.
  • <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>- Aspera 활성화된 Object Storage 서비스 인스턴스의 버킷 이름
  • <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>- Aspera 활성화된 Object Storage 서비스 인스턴스의 버킷 이름
  • <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>- Aspera 활성화된 Object Storage 서비스 인스턴스의 버킷 이름
  • <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 버전을 업데이트해야 합니다. 이 작업을 수행할 수 없는 경우 Python *용 인텔® 배포 설치를 사용할 수 있습니다. 이를 통해 문제 없이 Python 3.6.x 에 Aspera SDK 를 설치할 수 있습니다.

메타데이터 업데이트

기존 오브젝트의 메타데이터를 업데이트하는 데는 두 가지 방법이 있습니다.

  • 새 메타데이터와 원본 오브젝트 컨텐츠를 사용한 PUT 요청
  • 원본 오브젝트를 복사 소스로 지정하여 새 메타데이터로 COPY 요청 실행

PUT을 사용한 메타데이터 업데이트

참고: 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를 사용한 메타데이터 업데이트

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))

불변 오브젝트 스토리지 사용

기존 버킷에 보호 구성 추가

보호된 버킷에 작성된 오브젝트는 보호 기간이 만료되어 오브젝트에 대한 모든 법적 보존이 제거될 때까지 삭제할 수 없습니다. 오브젝트가 작성될 때 오브젝트 고유 값이 제공되지 않으면 버킷의 기본 보존 값이 오브젝트에 지정됩니다. 보호된 버킷에서 더 이상 보존되지 않는 오브젝트(보존 기간이 만료되어 오브젝트에 대한 법적 보존이 없음)를 겹쳐쓰면 다시 보존 상태가 됩니다. 새 보존 기간은 오브젝트 겹쳐쓰기 요청의 일부로서 제공될 수 있으며, 그렇지 않은 경우에는 버킷의 기본 보존 기간이 오브젝트에 지정됩니다.

보존 기간 설정 MinimumRetention, DefaultRetention, MaximumRetention 에서 지원되는 최소 및 최대 값은 최소 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 또는 이와 유사한 메소드)

오브젝트 메타데이터에 저장된 현재 보존 기간은 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에서 찾을 수 있습니다.