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

断点续传下载(C++ SDK)

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

首次发布时间2022.10.17 20:58:25

当下载大对象时,可能出现网络波动等情况导致下载对象失败,TOS C++ SDK 提供了重试机制保障下载对象的稳定性,但可能出现多次重试后仍无法完成下载的情况。针对上述情况,TOS C++ SDK 提供了断点续传下载的功能,借助本地 CheckPoint 的机制记录已下载成功的分片。当出现网络异常或机器故障等问题导致下载中断,可再次调用该接口以实现续传的效果。
断点续传下载将待下载的对象分割为多个分片,并支持并发下载,待所有分片下载完成后,合并成完整的文件。您可以设置断点续传下载的分片大小、下载分片的线程数、下载时客户端限速、事件回调函数等。同时也能在断点续传下载任务执行过程中,取消该任务。

注意事项

  • 下载对象前,您必须具有 tos:GetObject 权限,具体操作,请参见权限配置指南
  • 对于开启多版本的桶,下载指定版本对象时,您必须具有 tos:GetObjectVersion 权限,具体操作,请参见权限配置指南
  • 如果应用程序会在同一时刻大量下载同一个对象,您的访问速度会受到 TOS 带宽及地域的限制。建议您使用 CDN 产品,提升性能的同时也能降低您的成本。通过 CDN 访问 TOS 的详细信息,请参见使用 CDN 加速访问 TOS 资源
  • SDK 会将上传的状态信息记录在 Checkpoint 文件中,所以程序需要对 Checkpoint 文件有写权限。
  • 使用断点续传下载时,文件下载的进度信息会记录在 Checkpoint 文件中,如果下载过程中某一分片下载失败,再次下载时会从 Checkpoint 文件中记录的点继续下载,从而达到断点续传的效果。下载完成后, Checkpoint 文件会被删除。
  • 如果下载过程中文件的 ETag 发生变化、Part 丢失或被修改,则重新下载文件。

示例代码

断点续传下载

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

#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";
    // 下载Object到本地文件examplefile.txt,并保存到指定的本地路径中,例如/localpath/examplefile.txt,如果指定的本地文件存在会覆盖,不存在则新建。
    std::string filePath = "/localpath/examplefile.txt";
    // 记录断点记录文件的完整路径。只有当Object下载中断产生了断点记录文件后,如果需要继续下载该Object,才需要设置对应的断点记录文件。下载完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    // 断点续传下载
    DownloadFileInput input(bucketName, objectName);
    // 并发下载分片的线程数 1-1000
    input.setTaskNum(10);
    // 开启 checkpoint 会在本地生成断点续传记录文件
    input.setEnableCheckpoint(true);
    // 默认分片大小 20MB
    input.setPartSize(20 * 1024 * 1024);
    // 下载后文件的保存路径,不可为空,不可为文件夹,建议设置绝对路径
    input.setFilePath(filePath);
    auto output = client.downloadFile(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "DownloadFile failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "DownloadFile success. object etag is: " << output.result().getHeadObjectV2Output().getETags() << 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";
    // 下载Object到本地文件examplefile.txt,并保存到指定的本地路径中,例如/localpath/examplefile.txt,如果指定的本地文件存在会覆盖,不存在则新建。
    std::string filePath = "/localpath/examplefile.txt";
    // 记录断点记录文件的完整路径。只有当Object下载中断产生了断点记录文件后,如果需要继续下载该Object,才需要设置对应的断点记录文件。下载完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    // 断点续传下载
    DownloadFileInput 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.downloadFile(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "DownloadFile failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "DownloadFile success. object etag is: " << output.result().getHeadObjectV2Output().getETags() << std::endl;
    // 释放网络等资源
    CloseClient();
    return 0;
}

处理事件回调

downloadFile 接口调用过程会发送创建临时文件、下载分片、重命名临时文件等事件,您可以传入自定义接口来监听下载的相关事件,并实现自定义的业务逻辑。
以下代码用于自定义断点续传下载回调函数。

#include "TosClientV2.h"
using namespace VolcengineTos;

static void DownloadCallBack(std::shared_ptr<DownloadEvent> event) {
    DownloadEventType type_ = event->type_;
    bool error_ = event->error_;
    std::string bucket_ = event->bucket_;
    std::string key_ = event->key_;
    std::string versionId_ = event->versionId_;
    std::string filePath_ = event->filePath_;
    std::string fileInfo = bucket_ + key_ + versionId_ + filePath_;
    std::shared_ptr<std::string> checkpointFile_ = event->checkpointFile_;
    std::shared_ptr<std::string> tempFilePath_ = event->tempFilePath_;
    std::shared_ptr<DownloadPartInfo> downloadPartInfo_ = event->downloadPartInfo_;
    std::string downloadPartInfo = "";
    if (downloadPartInfo_ != nullptr) {
        downloadPartInfo = std::to_string(downloadPartInfo_->rangeStart_) + "," +
                           std::to_string(downloadPartInfo_->rangeEnd_) + "," +
                           std::to_string(downloadPartInfo_->partNumber_);
    }

    std::cout << "type:" << type_ << ","
              << "error:" << error_ << ","
              << "fileInfo:" << fileInfo << ","
              << "checkpointFile:" << *checkpointFile_ << ","
              << "tempFilePath:" << *tempFilePath_ << ","
              << "downloadPartInfo:" << downloadPartInfo << 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";
    // 下载Object到本地文件examplefile.txt,并保存到指定的本地路径中,例如/localpath/examplefile.txt,如果指定的本地文件存在会覆盖,不存在则新建。
    std::string filePath = "/localpath/examplefile.txt";
    // 记录断点记录文件的完整路径。只有当Object下载中断产生了断点记录文件后,如果需要继续下载该Object,才需要设置对应的断点记录文件。下载完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);


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

    auto output = client.downloadFile(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "DownloadFile failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "DownloadFile success. object etag is: " << output.result().getHeadObjectV2Output().getETags() << 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";
    // 下载Object到本地文件examplefile.txt,并保存到指定的本地路径中,例如/localpath/examplefile.txt,如果指定的本地文件存在会覆盖,不存在则新建。
    std::string filePath = "/localpath/examplefile.txt";
    // 记录断点记录文件的完整路径。只有当Object下载中断产生了断点记录文件后,如果需要继续下载该Object,才需要设置对应的断点记录文件。下载完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    // 断点续传下载
    DownloadFileInput 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.downloadFile(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "DownloadFile failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "DownloadFile success. object etag is: " << output.result().getHeadObjectV2Output().getETags() << std::endl;
    // 释放网络等资源
    CloseClient();
    return 0;
}

取消机制

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

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

static void threadFunction1(TosClientV2 client, DownloadFileInput input) {
    auto output = client.downloadFile(input);
    if (!output.isSuccess()) {
        std::cout << "DownloadFile failed." << output.error().String() << std::endl;
    }

    std::cout << "DownloadFile success. object etag is: " << output.result().getHeadObjectV2Output().getETags()  << 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";
    // 下载Object到本地文件examplefile.txt,并保存到指定的本地路径中,例如/localpath/examplefile.txt,如果指定的本地文件存在会覆盖,不存在则新建。
    std::string filePath = "/localpath/examplefile.txt";
    // 记录断点记录文件的完整路径。只有当Object下载中断产生了断点记录文件后,如果需要继续下载该Object,才需要设置对应的断点记录文件。下载完成后,该文件会被删除。
    // 如果未设置该值,默认与待上传的本地文件同路径。
    std::string CheckpointFilePath = "yourCheckpointFilepath";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    // 断点续传下载
    DownloadFileInput 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;
}