全部產品
Search
文件中心

Object Storage Service:追加上傳(Python SDK V2)

更新時間:Jul 31, 2025

追加上傳是指在已上傳的追加類型檔案(Appendable Object)末尾直接追加內容。本文介紹如何使用OSS Python SDK進行追加上傳。

注意事項

  • 本文範例程式碼以華東1(杭州)的地區IDcn-hangzhou為例,預設使用外網Endpoint,如果您希望通過與OSS同地區的其他阿里雲產品訪問OSS,請使用內網Endpoint。關於OSS支援的Region與Endpoint的對應關係,請參見OSS地區和訪問網域名稱

  • 當檔案不存在時,調用追加上傳方法會建立一個追加類型檔案。

  • 當檔案已存在時:

    • 如果檔案為追加類型檔案,且設定的追加位置和檔案當前長度相等,則直接在該檔案末尾追加內容。

    • 如果檔案為追加類型檔案,但是設定的追加位置和檔案當前長度不相等,則拋出PositionNotEqualToLength異常。

    • 如果檔案為非追加類型檔案,例如通過簡單上傳的檔案類型為Normal的檔案,則拋出ObjectNotAppendable異常。

許可權說明

阿里雲帳號預設擁有全部許可權。阿里雲帳號下的RAM使用者或RAM角色預設沒有任何許可權,需要阿里雲帳號或帳號管理員通過RAM PolicyBucket Policy授予操作許可權。

API

Action

說明

AppendObject

oss:PutObject

以追加寫的方式上傳檔案(Object)。

oss:PutObjectTagging

以追加寫的方式上傳檔案(Object)時,如果通過x-oss-tagging指定Object的標籤,則需要此操作的許可權。

方法定義

針對檔案追加上傳的情境,Python SDK V2新增了AppendFile方法以模仿檔案的讀寫行為,用於操作儲存空間裡的對象,以下列舉了AppendFile與AppendObject方法的具體說明:

方法名

說明

AppendFile

與AppendObject方法能力一致

最佳化了重傳時失敗後容錯處理

AppendObject

追加上傳, 最終檔案最大支援5GiB

支援CRC64資料校正(預設啟用)

支援進度條

進階版追加上傳API:AppendFile

調用AppendFile方法以追加寫的方式上傳資料。如果對象不存在,則建立追加類型的對象。如果對象存在,並且不為追加類型的對象,則返回錯誤。

AppendFile方法定義如下。

append_file(bucket: str, key: str, request_payer: str | None = None, create_parameter: AppendObjectRequest | None = None, **kwargs) → AppendOnlyFile

請求參數列表

參數名

類型

說明

bucket

str

設定儲存空間名

key

str

設定對象名

RequestPayer

str

啟用了要求者付費模式時,需要設定為'requester'

CreateParameter

AppendObjectRequest

用於首次上傳時,設定對象的元資訊,包括ContentType,Metadata,許可權,儲存類型等,具體請參見AppendObjectRequest

傳回值列表

類型

說明

AppendOnlyFile

追加檔案的執行個體,具體請參見AppendOnlyFile

其中,AppendOnlyFile類包含的方法說明如下:

方法名

說明

Close()

關閉檔案控制代碼,釋放資源

write(b)

將位元組資料寫入到檔案中,返回寫入的位元組數

write_from(b: str | bytes | Iterable[bytes] | IO[str] | IO[bytes])

將任意資料寫入到檔案中,返回寫入的位元組數

關於AppendFile方法的完整定義,請參見append_file

基礎版追加上傳API:AppendObject

append_object(request: AppendObjectRequest, **kwargs) → AppendObjectResult

請求參數列表

參數名

類型

說明

request

AppendObjectRequest

佈建要求參數,具體請參見AppendObjectRequest

傳回值列表

類型

說明

AppendObjectResult

傳回值,具體請參見AppendObjectResult

關於AppendObject方法的完整定義,請參見append_object

範例程式碼

(推薦)使用AppendFile追加上傳

import argparse
import alibabacloud_oss_v2 as oss

# 建立命令列參數解析器,並描述指令碼用途:樣本展示如何向OSS對象追加資料
parser = argparse.ArgumentParser(description="append file sample")

# 添加命令列參數 --region,表示儲存空間所在的地區,必需參數
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# 添加命令列參數 --bucket,表示要操作的儲存空間名稱,必需參數
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# 添加命令列參數 --endpoint,表示其他服務可用來訪問OSS的網域名稱,非必需參數
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# 添加命令列參數 --key,表示對象(檔案)在OSS中的鍵名,必需參數
parser.add_argument('--key', help='The name of the object.', required=True)

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

    # 從環境變數中載入訪問OSS所需的認證資訊,用於身分識別驗證
    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)

    # 定義要追加的資料
    data1 = b'hello'
    data2 = b' world. '

    # 第一次追加資料
    with client.append_file(bucket=args.bucket, key=args.key) as f:
        append_f = f
        f.write(data1)
    # 列印第一次追加後的檔案狀態
    print(f'closed: {append_f.closed},'
          f' name: {append_f.name}'
    )

    # 第二次追加資料
    with client.append_file(bucket=args.bucket, key=args.key) as f:
        append_f = f
        f.write(data2)
    # 列印第二次追加後的檔案狀態
    print(f'closed: {append_f.closed},'
          f' name: {append_f.name}'
    )

    # 擷取追加後的對象內容
    result = client.get_object(oss.GetObjectRequest(
        bucket=args.bucket,
        key=args.key,
    ))
    # 列印擷取對象的結果
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' content: {result.body.content.decode("utf-8")}'
    )

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

使用AppendObject追加上傳

import argparse
import alibabacloud_oss_v2 as oss

# 建立一個命令列參數解析器
parser = argparse.ArgumentParser(description="append object sample")

# 添加命令列參數
# --region: 指定OSS儲存空間所在的地區
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# --bucket: 指定要操作的儲存空間名稱
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# --endpoint: 選擇性參數,指定訪問OSS服務的網域名稱
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# --key: 指定對象(檔案)在OSS中的鍵名
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # 解析命令列輸入的參數
    args = parser.parse_args()

    # 從環境變數中載入OSS所需的認證資訊
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK提供的預設配置建立設定物件
    cfg = oss.config.load_default()

    # 設定認證資訊提供者為之前建立的對象
    cfg.credentials_provider = credentials_provider

    # 根據使用者輸入設定OSS用戶端使用的地區
    cfg.region = args.region

    # 如果使用者提供了自訂的endpoint,則更新配置
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用上述配置建立OSS用戶端執行個體
    client = oss.Client(cfg)

    # 定義要追加的資料
    data1 = b'hello'
    data2 = b' world'

    # 第一次追加資料
    result = client.append_object(oss.AppendObjectRequest(
        bucket=args.bucket,  # 指定目標儲存空間
        key=args.key,  # 指定對象的鍵名
        position=0,  # 追加的起始位置,初始為0
        body=data1,  # 要追加的資料
    ))

    # 列印第一次追加的結果
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' version id: {result.version_id},'
          f' hash crc64: {result.hash_crc64},'
          f' next position: {result.next_position},' 
    )

    # 第二次追加資料
    result = client.append_object(oss.AppendObjectRequest(
        bucket=args.bucket,  # 指定目標儲存空間
        key=args.key,  # 指定對象的鍵名
        position=result.next_position,  # 從上一次追加的下一個位置開始
        body=data2,  # 要追加的資料
    ))

    # 列印第二次追加的結果
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' version id: {result.version_id},'
          f' hash crc64: {result.hash_crc64},'
          f' next position: {result.next_position},'
    )

# 當此指令碼被直接運行時,調用main函數
if __name__ == "__main__":
    main()

常見使用情境

追加上傳顯示進度條

import argparse
import alibabacloud_oss_v2 as oss

# 建立一個命令列參數解析器
parser = argparse.ArgumentParser(description="append object sample")

# 添加命令列參數
# --region: 指定OSS儲存空間所在的地區
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# --bucket: 指定要操作的儲存空間名稱
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# --endpoint: 選擇性參數,指定訪問OSS服務的網域名稱
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# --key: 指定對象(檔案)在OSS中的鍵名
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # 解析命令列輸入的參數
    args = parser.parse_args()

    # 從環境變數中載入OSS所需的認證資訊
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK提供的預設配置建立設定物件
    cfg = oss.config.load_default()

    # 設定認證資訊提供者為之前建立的對象
    cfg.credentials_provider = credentials_provider

    # 根據使用者輸入設定OSS用戶端使用的地區
    cfg.region = args.region

    # 如果使用者提供了自訂的endpoint,則更新配置
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用上述配置建立OSS用戶端執行個體
    client = oss.Client(cfg)

    # 定義一個字典變數 progress_state 用於儲存上傳進度狀態,初始值為 0
    progress_state = {'saved': 0}
    def _progress_fn(n, written, total):
        # 使用字典儲存累計寫入的位元組數,避免使用 global 變數
        progress_state['saved'] += n

        # 計算當前上傳百分比,將已寫入位元組數與總位元組數進行除法運算後取整
        rate = int(100 * (float(written) / float(total)))

        # 列印當前上傳進度,\r 表示回到行首,實現命令列中即時重新整理效果
        # end='' 表示不換行,使下一次列印覆蓋當前行
        print(f'\r上傳進度:{rate}% ', end='')

    # 定義要追加的資料
    data1 = b'hello'
    data2 = b' world'

    # 第一次追加資料
    result = client.append_object(oss.AppendObjectRequest(
        bucket=args.bucket,  # 指定目標儲存空間
        key=args.key,  # 指定對象的鍵名
        position=0,  # 追加的起始位置,初始為0
        body=data1,  # 要追加的資料
        progress_fn=_progress_fn,  # 設定進度回呼函數
    ))

    # 列印第一次追加的結果
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' version id: {result.version_id},'
          f' hash crc64: {result.hash_crc64},'
          f' next position: {result.next_position},'
    )

    # 第二次追加資料
    result = client.append_object(oss.AppendObjectRequest(
        bucket=args.bucket,  # 指定目標儲存空間
        key=args.key,  # 指定對象的鍵名
        position=result.next_position,  # 從上一次追加的下一個位置開始
        body=data2,  # 要追加的資料
        progress_fn=_progress_fn,  # 設定進度回呼函數
    ))

    # 列印第二次追加的結果
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' version id: {result.version_id},'
          f' hash crc64: {result.hash_crc64},'
          f' next position: {result.next_position},'
    )

# 當此指令碼被直接運行時,調用main函數
if __name__ == "__main__":
    main()

相關文檔