You need to enable JavaScript to run this app.
导航

断点续传拷贝(C++ SDK)

最近更新时间2024.02.04 18:31:05

首次发布时间2023.03.15 15:05:53

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

注意事项

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

断点续传拷贝

以下代码用于断点续传拷贝 srcbucket 桶中 srcdir/exampleobject.txt 对象到 destbucket 桶中,并设置对象对象名为 destdir/exampleobject.txt 以及失败后重入下载。若复制过程中返回网络超时的报错,则您可以相同参数调用 resumableCopyObject 后实现断点续传下载重入。

#include "TosClientV2.h"
using namespace VolcengineTos;

int main(void){
    // 初始化 TOS 账号信息
    // Your Region 填写 Bucket 所在 Region
    std::string region = "Your Region";
    std::string accessKey = std::getenv("TOS_ACCESS_KEY");
    std::string secretKey = std::getenv("TOS_SECRET_KEY");
    // 填写 Bucket 名称,例如 destbucket
    std::string bucketName = "destbucket";
    // 填写Object完整路径,完整路径中不能包含Bucket名称,destdir/exampleobject.txt。
    std::string objectName = "destdir/exampleobject.txt";
    // 填写 Bucket 名称,例如 srcbucket
    std::string srcBucketName = "srcbucket";
    // 填写Object完整路径,完整路径中不能包含Bucket名称,srcdir/exampleobject.txt。
    std::string srcObjectName = "srcdir/exampleobject.txt";
    // 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    ResumableCopyObjectInput input;
    // 对象名和桶名
    input.setBucket(bucketName);
    input.setKey(objectName);
    input.setSrcBucket(srcBucketName);
    input.setSrcKey(srcObjectName);

    // 并发下载分片的线程数 1-1000
    input.setTaskNum(1);
    // 开启 checkpoint 会在本地生成断点续传记录文件
    input.setEnableCheckpoint(true);
    // 默认分片大小 20MB
    input.setPartSize(5 * 1024 * 1024);

    auto output = client.resumableCopyObject(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "ResumableCopyObject failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "ResumableCopyObject success. object etag is: " << output.result().getETag() << std::endl;
    // 释放网络等资源
    CloseClient();
    return 0;
}

处理事件回调

resumableCopyObject 接口调用过程会发送初始化分段拷贝任务、拷贝分段、合并分段等事件,您可以传入自定义接口来监听下载的相关事件,并实现自定义的业务逻辑。
以下代码用于自定义断点续传复制回调函数。

#include "TosClientV2.h"
using namespace VolcengineTos;

static void CopyCallBack(std::shared_ptr<CopyEvent> event) {
    CopyEventType type_ = event->type_;
    bool error_ = event->error_;
    std::string bucket_ = event->bucket_;
    std::string key_ = event->key_;
    std::string fileInfo = bucket_ + key_;
    std::shared_ptr<std::string> uploadId_ = event->uploadId_;
    std::shared_ptr<std::string> checkpointFile_ = event->checkpointFile_;
    std::shared_ptr<CopyPartInfo> uploadPartInfo_ = event->copyPartInfo_;
    std::string uploadPartInfo = "";
    if (uploadPartInfo_ != nullptr) {
        uploadPartInfo = std::to_string(uploadPartInfo_->partNumber_) + "," +
                         std::to_string(uploadPartInfo_->copySourceRangeStart_) + "," +
                         std::to_string(uploadPartInfo_->copySourceRangeEnd_) + "," + *(uploadPartInfo_->eTag_);
    }
    std::cout << "type:" << type_ << ","
              << "error:" << error_ << ","
              << "fileInfo:" << fileInfo << ","
              << "checkpointFile:" << *checkpointFile_ << ","
              << "uploadId:" << *uploadId_ << ","
              << "uploadPartInf:" << uploadPartInfo << std::endl;
}

int main(void){
    // 初始化 TOS 账号信息
    // Your Region 填写 Bucket 所在 Region
    std::string region = "Your Region";
    std::string accessKey = std::getenv("TOS_ACCESS_KEY");
    std::string secretKey = std::getenv("TOS_SECRET_KEY");
    // 填写 Bucket 名称,例如 destbucket
    std::string bucketName = "destbucket";
    // 填写Object完整路径,完整路径中不能包含Bucket名称,destdir/exampleobject.txt。
    std::string objectName = "destdir/exampleobject.txt";
    // 填写 Bucket 名称,例如 srcbucket
    std::string srcBucketName = "srcbucket";
    // 填写Object完整路径,完整路径中不能包含Bucket名称,srcdir/exampleobject.txt。
    std::string srcObjectName = "srcdir/exampleobject.txt";
    // 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    ResumableCopyObjectInput input;
    // 对象名和桶名
    input.setBucket(bucketName);
    input.setKey(objectName);
    input.setSrcBucket(srcBucketName);
    input.setSrcKey(srcObjectName);

    // 并发下载分片的线程数 1-1000
    input.setTaskNum(1);
    // 开启 checkpoint 会在本地生成断点续传记录文件
    input.setEnableCheckpoint(true);
    // 默认分片大小 20MB
    input.setPartSize(5 * 1024 * 1024);
    // 设置 CopyEvent
    CopyEventListener copyHandler = {CopyCallBack};
    input.setCopyEventListener(copyHandler);
    auto output = client.resumableCopyObject(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "ResumableCopyObject failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "ResumableCopyObject success. object etag is: " << output.result().getETag() << std::endl;
    // 释放网络等资源
    CloseClient();
    return 0;
}

取消机制

resumableCopyObject 接口支持您主动暂停或取消断点续传任务。暂停断点续传任务会停止下载,再次调用 resumableCopyObject 时可以从上次暂停的位置继续下载。取消断点续传任务会停止下载,删除本地的 CheckPoint 文件和下载的临时文件,再次调用 resumableCopyObject 时会重新开始上传。
以下代码展示如何暂停或取消断点续传复制。

#include "TosClientV2.h"
#include <thread>
using namespace VolcengineTos;

static void threadFunction1(TosClientV2 client, ResumableCopyObjectInput input) {
    auto output = client.resumableCopyObject(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "ResumableCopyObject failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
    }
    std::cout << "ResumableCopyObject success. object etag is: " << output.result().getETag() << std::endl;
}

static void threadFunction2(std::shared_ptr<CancelHook> CancelHook) {
    // false 代表不清除 checkpoint 等信息。true 代表清除 checkpoint 等信息
    CancelHook->Cancel(false);
}

int main(void){
    // 初始化 TOS 账号信息
    // Your Region 填写 Bucket 所在 Region
    std::string region = "Your Region";
    std::string accessKey = std::getenv("TOS_ACCESS_KEY");
    std::string secretKey = std::getenv("TOS_SECRET_KEY");
    // 填写 Bucket 名称,例如 destbucket
    std::string bucketName = "destbucket";
    // 填写Object完整路径,完整路径中不能包含Bucket名称,destdir/exampleobject.txt。
    std::string objectName = "destdir/exampleobject.txt";
    // 填写 Bucket 名称,例如 srcbucket
    std::string srcBucketName = "srcbucket";
    // 填写Object完整路径,完整路径中不能包含Bucket名称,srcdir/exampleobject.txt。
    std::string srcObjectName = "srcdir/exampleobject.txt";
    // 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    ResumableCopyObjectInput input;
    // 对象名和桶名
    input.setBucket(bucketName);
    input.setKey(objectName);
    input.setSrcBucket(srcBucketName);
    input.setSrcKey(srcObjectName);

    // 并发下载分片的线程数 1-1000
    input.setTaskNum(1);
    // 开启 checkpoint 会在本地生成断点续传记录文件
    input.setEnableCheckpoint(true);
    // 默认分片大小 20MB
    input.setPartSize(5 * 1024 * 1024);
    // 设置 cancelHook
    std::shared_ptr<CancelHook> CancelHook(NewCancelHook());
    input.setCancelHook(CancelHook);

    // 线程1中执行断点续传上传接口
    std::thread thread1(threadFunction1, client, input);
    thread1.detach();
    TimeUtils::sleepSecondTimes(5);
    // 运行五秒后在线程2中中断该次请求
    std::thread thread2(threadFunction2, CancelHook);
    thread2.join();
    // 释放网络等资源
    CloseClient();
    return 0;
}