You need to enable JavaScript to run this app.
导航
断点续传拷贝(Python SDK)
最近更新时间:2024.09.27 14:38:29首次发布时间:2023.02.02 17:32:41

断点续传复制适用于通过 TOS Python SDK 在单个桶内或同区域的两个桶之间复制大对象的场景。TOS Python SDK 提供了断点续传下载的功能,借助本地 CheckPoint 的机制记录已成功复制的分段,当出现网络异常或机器故障等问题导致分段复制中断,可再次调用该接口以实现续传的效果。断点续传复制将待复制的对象分割为多个分段,并支持并发复制,待所有分段复制完成后,合并成完整的文件。您可以设置断点续传复制的分段大小、复制分段的线程数、事件回调函数等。同时也能在断点续传复制任务执行过程中,取消该任务。

注意事项

  • 拷贝文件不支持跨区域的桶间拷贝。
  • 拷贝对象时,账号必须具备源对象的读取权限和目标桶的写入权限。
  • 拷贝对象时,可以保留所有元数据(默认值)或指定新的元数据。但ACL并未被保留,而是设置为私有。

示例代码

断点续传复制

以下代码用于断点续传拷贝 src_bucket_name 桶中 src_object_key 对象到 bucket_name 桶中,并设置对象对象名为 object_key 以及失败后重入下载。若复制过程中返回网络超时的报错,则您可以以相同参数调用 resumable_copy_object 后实现断点续传下载重入。

import os
import tos

# 从环境变量获取 AK 和 SK 信息。
ak = os.getenv('TOS_ACCESS_KEY')
sk = os.getenv('TOS_SECRET_KEY')
# your endpoint 和 your region 填写Bucket 所在区域对应的Endpoint。# 以华北2(北京)为例,your endpoint 填写 tos-cn-beijing.volces.com,your region 填写 cn-beijing。
endpoint = "your endpoint"
region = "your region"
# 目标桶的名称
bucket_name = "bucket-test"
# 拷贝到目标桶后的对象名称
object_key = "object-test"
# 源桶的名称
src_bucket_name = "your src bucket name"
# 源对象的名称
src_object_key = "your src object key"
try:
    # 创建 TosClientV2 对象,对桶和对象的操作都通过 TosClientV2 实现
    client = tos.TosClientV2(ak, sk, endpoint, region)
    client.resumable_copy_object(bucket_name, object_key, src_bucket_name, src_object_key,
                                 # 通过task num配置并发线程数,
                                 task_num=3,
                                 # 通过part_size配置分片大小
                                 part_size=20 * 1024 * 1024)
except tos.exceptions.TosClientError as e:
    # 操作失败,捕获客户端异常,一般情况为非法请求参数或网络异常
    print('fail with client error, message:{}, cause: {}'.format(e.message, e.cause))
except tos.exceptions.TosServerError as e:
    # 操作失败,捕获服务端异常,可从返回信息中获取详细错误信息
    print('fail with server error, code: {}'.format(e.code))
    # request id 可定位具体问题,强烈建议日志中保存
    print('error with request id: {}'.format(e.request_id))
    print('error with message: {}'.format(e.message))
    print('error with http code: {}'.format(e.status_code))
    print('error with ec: {}'.format(e.ec))
    print('error with request url: {}'.format(e.request_url))
except Exception as e:
    print('fail with unknown error: {}'.format(e))

处理事件回调

以下代码用于自定义断点续传拷贝回调函数。

import os
import tos
from tos import CopyEventType

# 从环境变量获取 AK 和 SK 信息。
ak = os.getenv('TOS_ACCESS_KEY')
sk = os.getenv('TOS_SECRET_KEY')
# your endpoint 和 your region 填写Bucket 所在区域对应的Endpoint。# 以华北2(北京)为例,your endpoint 填写 tos-cn-beijing.volces.com,your region 填写 cn-beijing。
endpoint = "your endpoint"
region = "your region"
# 目标桶的名称
bucket_name = "bucket-test"
# 拷贝到目标桶后的对象名称
object_key = "object-test"
# 源桶的名称
src_bucket_name = "your src bucket name"
# 源对象的名称
src_object_key = "your src object key"
try:
    # 创建 TosClientV2 对象,对桶和对象的操作都通过 TosClientV2 实现
    def copy_event(copy_event_type: CopyEventType, err, bucket, key, upload_id, src_bucket, src_key, src_version_id, checkpoint, copy_part):
        print(copy_event_type, err, bucket, key, upload_id, src_bucket, src_key, src_version_id, checkpoint, copy_part)

    client = tos.TosClientV2(ak, sk, endpoint, region)
    client.resumable_copy_object(bucket_name, object_key, src_bucket_name, src_object_key,
                                 # 通过task num配置并发线程数,
                                 task_num=3,
                                 # 通过part_size配置分片大小
                                 part_size=20 * 1024 * 1024,
                                 copy_event_listener=copy_event)
except tos.exceptions.TosClientError as e:
    # 操作失败,捕获客户端异常,一般情况为非法请求参数或网络异常
    print('fail with client error, message:{}, cause: {}'.format(e.message, e.cause))
except tos.exceptions.TosServerError as e:
    # 操作失败,捕获服务端异常,可从返回信息中获取详细错误信息
    print('fail with server error, code: {}'.format(e.code))
    # request id 可定位具体问题,强烈建议日志中保存
    print('error with request id: {}'.format(e.request_id))
    print('error with message: {}'.format(e.message))
    print('error with http code: {}'.format(e.status_code))
    print('error with ec: {}'.format(e.ec))
    print('error with request url: {}'.format(e.request_url))
except Exception as e:
    print('fail with unknown error: {}'.format(e))

取消机制

以下代码用于暂停或取消断点续传拷贝任务。

import time
from threading import Thread

import os
import tos
from tos import CopyEventType
from tos.checkpoint import CancelHook

# 从环境变量获取 AK 和 SK 信息。
ak = os.getenv('TOS_ACCESS_KEY')
sk = os.getenv('TOS_SECRET_KEY')
# your endpoint 和 your region 填写Bucket 所在区域对应的Endpoint。# 以华北2(北京)为例,your endpoint 填写 tos-cn-beijing.volces.com,your region 填写 cn-beijing。
endpoint = "your endpoint"
region = "your region"
# 目标桶的名称
bucket_name = "bucket-test"
# 拷贝到目标桶后的对象名称
object_key = "object-test"
# 源桶的名称
src_bucket_name = "your src bucket name"
# 源对象的名称
src_object_key = "your src object key"
try:
    # 继承 CancelHook 类实现断点续传下载任务取消功能
    class MyCancel(CancelHook):
        def cancel(self, is_abort: bool):
            # is_abort 为 true 时删除上下文信息并 abort 分段上传任务,为 false 时只是中断当前执行
            # 重写 cancel 方法时必须调用 父类的 cancel 方法
            # 模拟 10 秒后取消任务
            time.sleep(10)
            super(MyCancel, self).cancel(is_abort=is_abort)
            print('some user define')

    cancel = MyCancel()

    t1 = Thread(target=cancel.cancel, args=(False,))
    t1.start()

    client = tos.TosClientV2(ak, sk, endpoint, region)
    client.resumable_copy_object(bucket_name, object_key, src_bucket_name, src_object_key,
                                 # 通过task num配置并发线程数,
                                 task_num=3,
                                 # 通过part_size配置分片大小
                                 part_size=20 * 1024 * 1024,
                                 cancel_hook=cancel)
except tos.exceptions.TosClientError as e:
    # 操作失败,捕获客户端异常,一般情况为非法请求参数或网络异常
    print('fail with client error, message:{}, cause: {}'.format(e.message, e.cause))
except tos.exceptions.TosServerError as e:
    # 操作失败,捕获服务端异常,可从返回信息中获取详细错误信息
    print('fail with server error, code: {}'.format(e.code))
    # request id 可定位具体问题,强烈建议日志中保存
    print('error with request id: {}'.format(e.request_id))
    print('error with message: {}'.format(e.message))
    print('error with http code: {}'.format(e.status_code))
    print('error with ec: {}'.format(e.ec))
    print('error with request url: {}'.format(e.request_url))
except Exception as e:
    print('fail with unknown error: {}'.format(e))