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

断点续传(C++ SDK)

最近更新时间2024.02.04 18:30:57

首次发布时间2022.05.31 14:41:57

通过断点续传上传的方式将文件上传到 TOS 前,您可以设置分片大小、上传分片的线程数、上传时客户端限速、事件回调函数等。同时也能在断点续传上传任务执行过程中,取消该任务。若出现网络异常等情况导致文件上传失败时,将从断点记录处继续上传未上传完成的部分。

注意事项

  • 上传对象前,您必须具有 tos:PutObject 权限,具体操作,请参见权限配置指南
  • 上传对象时,对象名必须满足一定规范,详细信息,请参见对象命名规范
  • TOS 是面向海量存储设计的分布式对象存储产品,内部分区存储了对象索引数据,为横向扩展您上传对象和下载对象时的最大吞吐量,和减小热点分区的概率,请您避免使用字典序递增的对象命名方式,详细信息,请参见性能优化
  • 如果桶中已经存在同名对象,则新对象会覆盖已有的对象。如果您的桶开启了版本控制,则会保留原有对象,并生成一个新版本号用于标识新上传的对象。
  • SDK 会将上传的状态信息记录在 Checkpoint 文件中,所以程序需要对 Checkpoint 文件有写权限。
  • 使用断点续传上传时,文件上传的进度信息会记录在 Checkpoint 文件中,如果上传过程中某一分片上传失败,再次上传时会 Checkpoint 文件中记录的点继续上传。上传完成后, Checkpoint 文件会被删除。
  • 如果上传过程中本地文件发生了改变,则会重新上传所有分片。

示例代码

断点续传上传

以下代码用于断点续传上传将本地文件上传到目标桶 examplebucket 中的 exampledir/exampleobject.txt 对象。若上传过程中返回网络超时的报错,则您以相同参数调用 uploadFile 后可实现断点重入上传。

#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 名称,例如 examplebucket
    std::string bucketName = "examplebucket";
    // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
    std::string objectName = "exampledir/exampleobject.txt";
    // 填写本地文件完整路径,例如/localpath/examplefile.txt,其中localpath为本地文件examplefile.txt所在本地路径
    std::string filePath = "/localpath/examplefile.txt";
    // 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    // 断点续传上传
    UploadFileV2Input input(bucketName, objectName);
    // 并发下载分片的线程数 1-1000
    input.setTaskNum(10);
    // 开启 checkpoint 会在本地生成断点续传记录文件
    input.setEnableCheckpoint(true);
    // 默认分片大小 20MB
    input.setPartSize(20 * 1024 * 1024);
    // 待上传文件的路径,不可为空,不可为文件夹,建议设置绝对路径
    input.setFilePath(filePath);
    auto output = client.uploadFile(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "UploadFile failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "UploadFile success. object etag is: " << output.result().getETag() << std::endl;
    // 释放网络等资源
    CloseClient();
    return 0;
}

处理进度条

以下代码用于配置断点续传上传进度条功能。

#include "TosClientV2.h"
using namespace VolcengineTos;

static void ProgressCallback(std::shared_ptr<DataTransferStatus> datatransferstatus) {
    int64_t consumedBytes = datatransferstatus->consumedBytes_;
    int64_t totalBytes = datatransferstatus->totalBytes_;
    int64_t rwOnceBytes = datatransferstatus->rwOnceBytes_;
    DataTransferType type = datatransferstatus->type_;
    int64_t rate = 100 * consumedBytes / totalBytes;
    std::cout << "rate:" << rate << ","
              << "ConsumedBytes:" << consumedBytes << ","
              << "totalBytes:" << totalBytes << ","
              << "rwOnceBytes:" << rwOnceBytes << ","
              << "DataTransferType:" << type << 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 名称,例如 examplebucket
    std::string bucketName = "examplebucket";
    // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
    std::string objectName = "exampledir/exampleobject.txt";
    // 填写本地文件完整路径,例如/localpath/examplefile.txt,其中localpath为本地文件examplefile.txt所在本地路径
    std::string filePath = "/localpath/examplefile.txt";
    // 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    // 断点续传上传
    UploadFileV2Input input(bucketName, objectName);
    // 并发下载分片的线程数 1-1000
    input.setTaskNum(10);
    // 开启 checkpoint 会在本地生成断点续传记录文件
    input.setEnableCheckpoint(true);
    // 默认分片大小 20MB
    input.setPartSize(20 * 1024 * 1024);
    // 待上传文件的路径,不可为空,不可为文件夹,建议设置绝对路径
    input.setFilePath(filePath);
    // 设置进度条
    DataTransferListener processHandler = {ProgressCallback, nullptr};
    input.setDataTransferListener(processHandler);

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

处理事件回调

uploadFile 接口调用过程会发送初始化分片、上传分片、合并分片等事件,您可以传入自定义接口来监听上传的相关事件,并实现自定义的业务逻辑。以下代码用于展示自定义断点续传上传回调函数功能。

#include "TosClientV2.h"
using namespace VolcengineTos;

static void UploadCallBack(std::shared_ptr<UploadEvent> event) {
    UploadEventType 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<UploadPartInfo> uploadPartInfo_ = event->uploadPartInfo_;
    std::string uploadPartInfo = "";
    if (uploadPartInfo_ != nullptr) {
        uploadPartInfo = std::to_string(uploadPartInfo_->partSize_) + "," + std::to_string(uploadPartInfo_->offset_) +
                         "," + std::to_string(uploadPartInfo_->partNumber_) + "," + *(uploadPartInfo_->eTag_) + "," +
                         std::to_string(*(uploadPartInfo_->hashCrc64ecma_));
    }
    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 名称,例如 examplebucket
    std::string bucketName = "examplebucket";
    // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
    std::string objectName = "exampledir/exampleobject.txt";
    // 填写本地文件完整路径,例如/localpath/examplefile.txt,其中localpath为本地文件examplefile.txt所在本地路径
    std::string filePath = "/localpath/examplefile.txt";
    // 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    // 断点续传上传
    UploadFileV2Input input(bucketName, objectName);
    // 并发下载分片的线程数 1-1000
    input.setTaskNum(10);
    // 开启 checkpoint 会在本地生成断点续传记录文件
    input.setEnableCheckpoint(true);
    // 默认分片大小 20MB
    input.setPartSize(20 * 1024 * 1024);
    // 待上传文件的路径,不可为空,不可为文件夹,建议设置绝对路径
    input.setFilePath(filePath);
    // 设置 UploadEvent
    UploadEventListener uploadHandler = {UploadCallBack};
    input.setUploadEventListener(uploadHandler);

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

设置客户端限速

以下代码用于设置断点续传上传客户端限速。

#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 名称,例如 examplebucket
    std::string bucketName = "examplebucket";
    // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
    std::string objectName = "exampledir/exampleobject.txt";
    // 填写本地文件完整路径,例如/localpath/examplefile.txt,其中localpath为本地文件examplefile.txt所在本地路径
    std::string filePath = "/localpath/examplefile.txt";
    // 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    // 断点续传上传
    UploadFileV2Input input(bucketName, objectName);
    // 并发下载分片的线程数 1-1000
    input.setTaskNum(10);
    // 开启 checkpoint 会在本地生成断点续传记录文件
    input.setEnableCheckpoint(true);
    // 默认分片大小 20MB
    input.setPartSize(20 * 1024 * 1024);
    // 待上传文件的路径,不可为空,不可为文件夹,建议设置绝对路径
    input.setFilePath(filePath);
    // 设置 rateLimiter
    std::shared_ptr<RateLimiter> RateLimiter(NewRateLimiter(20 * 1024 * 1024, 5 * 1024 * 1024));
    input.setRateLimiter(RateLimiter);

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

取消机制

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

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

static void threadFunction1(TosClientV2 client, UploadFileV2Input input) {
    auto output = client.uploadFile(input);
    if (!output.isSuccess()) {
        std::cout << "UploadFile failed." << output.error().String() << std::endl;
    }
    std::cout << "UploadFile 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 名称,例如 examplebucket
    std::string bucketName = "examplebucket";
    // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
    std::string objectName = "exampledir/exampleobject.txt";
    // 填写本地文件完整路径,例如/localpath/examplefile.txt,其中localpath为本地文件examplefile.txt所在本地路径
    std::string filePath = "/localpath/examplefile.txt";
    // 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    // 断点续传上传
    UploadFileV2Input input(bucketName, objectName);
    // 并发下载分片的线程数 1-1000
    input.setTaskNum(10);
    // 开启 checkpoint 会在本地生成断点续传记录文件
    input.setEnableCheckpoint(true);
    // 默认分片大小 20MB
    input.setPartSize(20 * 1024 * 1024);
    // 待上传文件的路径,不可为空,不可为文件夹,建议设置绝对路径
    input.setFilePath(filePath);
    // 设置 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);
    thread1.join();
    thread2.join();
    // 释放网络等资源
    CloseClient();
    return 0;
}