You need to enable JavaScript to run this app.
导航
多版本场景(C++ SDK)
最近更新时间:2024.02.04 18:31:04首次发布时间:2023.01.29 15:35:46

版本控制应用于桶中所有对象。通过开启桶的版本控制,您可以在错误删除或者覆盖对象后,将对象回恢复至任意的历史版本。
目前支持多版本的接口包含 GetObject、GetObjectACL、CopyObject、UploadPartCopy、DeleteObject等。调用相关接口时,您可通过可选参数 versionID 指定操作对象的具体版本。
TOS 中桶的版本状态包含未开启、开启版本控制和暂停版本控制三种,本文介绍桶的多版本管理。

注意事项

  • 管理桶的多版本状态,您必须具备 tos:PutBucketVersioning 权限。
  • 查询桶的多版本状态,您必须具备 tos:GetBucketVersioning 权限。

设置桶版本控制状态

以下代码用于设置桶状态为开启多版本(Enable)状态。

#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";

    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);
    PutBucketVersioningInput input(bucketName,VersioningStatusType::Enabled);

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

    // 释放网络等资源
    CloseClient();
    return 0;
}

以下代码用于设置桶状态为暂停版本控制状态(Suspended)。

#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";

    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);
    PutBucketVersioningInput input(bucketName,VersioningStatusType::Suspended);

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

    // 释放网络等资源
    CloseClient();
    return 0;
}

获取桶的版本控制状态

以下代码用于获取桶 examplebucket 的版本控制状态信息。

#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";

    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);
    GetBucketVersioningInput input(bucketName);

    auto output = client.getBucketVersioning(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "GetBucketVersioning failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "GetBucketVersioning success." << std::endl;
    std::cout << "versioning statue" << output.result().getStringFormatVersioningStatus() << std::endl;
    // 释放网络等资源
    CloseClient();
    return 0;
}

下载多版本对象

以下代码用于下载桶 examplebucket 中的对象 exampledir/exampleobject.txt 的指定版本到内存。

#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";
    // 填写对象的 versionId
    std::string versionId = "your object version";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    GetObjectV2Input input(bucketName, objectName);
    input.setVersionId(versionId);
    auto output = client.getObject(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "GetObject failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }

    std::cout << "GetObject success. the object etag:" << output.result().getETags()  << std::endl;

    // 释放网络等资源
    CloseClient();
    return 0;
}

删除多版本对象

以下代码用于删除指定桶 examplebucket 中的 exampledir/exampleobject.txt 对象的指定版本。

#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";
    // 填写对象的 versionId
    std::string versionId = "your object version";

    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    DeleteObjectInput input(bucketName,objectName);
    input.setVersionID(versionId);
    auto output = client.deleteObject(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "DeleteObject failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }

    std::cout << "DeleteObject success." << std::endl;
    std::cout << " version id is:" <<  output.result().getVersionId()
              << " is delete marker:" << output.result().isDeleteMarker() << 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";
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    ListObjectVersionsV2Input input(bucketName);
    bool isTruncated = true;
    std::string nextKeyMarker = "";
    std::string nextVersionIdMarker = "";
    DeleteObjectInput deleteObjectInput;
    deleteObjectInput.setBucket(bucketName);
    while(isTruncated){
        input.setKeyMarker(nextKeyMarker);
        input.setVersionIdMarker(nextVersionIdMarker);
        auto output = client.listObjectVersions(input);
        if (!output.isSuccess()) {
            // 异常处理
            std::cout << "ListObjects failed." << output.error().String() << std::endl;
            // 释放网络等资源
            CloseClient();
            return -1;
        }
 
        nextKeyMarker = output.result().getNextKeyMarker();
        nextVersionIdMarker = output.result().getNextVersionIdMarker();
        isTruncated = output.result().isTruncated();

        for (const auto& versions : output.result().getVersions()) {
            deleteObjectInput.setKey(versions.getKey());
            deleteObjectInput.setVersionID(versions.getVersionId());
            auto deleteOutput = client.deleteObject(deleteObjectInput);
            if (!deleteOutput.isSuccess()){
                if(output.error().getStatusCode() != 404 && output.error().getCode() != "NoSuchKey"){
                    std::cout << "DeleteObject failed:" << deleteOutput.error().String() << std::endl;
                    // 释放网络等资源
                    CloseClient();
                    return -1;
                }
            }
        }
        for (const auto& deleteMarker : output.result().getDeleteMarkers()) {
            deleteObjectInput.setKey(deleteMarker.getKey());
            deleteObjectInput.setVersionID(deleteMarker.getVersionId());
            auto deleteOutput = client.deleteObject(deleteObjectInput);
            if (!deleteOutput.isSuccess()){
                if(output.error().getStatusCode() != 404 && output.error().getCode() != "NoSuchKey"){
                    std::cout << "DeleteObject failed:" << deleteOutput.error().String() << std::endl;
                    // 释放网络等资源
                    CloseClient();
                    return -1;
                }
            }
        }
    }

    // 列举已上传分片
    ListMultipartUploadsV2Input input2(bucketName);
    AbortMultipartUploadInput abortMultipartUploadInput;
    abortMultipartUploadInput.setBucket(bucketName);
    // isTruncated用于控制是否列举完全,nextKeyMarker用于递归列举
    isTruncated = true;
    nextKeyMarker = "";
    while(isTruncated){
        input2.setKeyMarker(nextKeyMarker);
        auto output = client.listMultipartUploads(input2);
        if (!output.isSuccess()) {
            // 异常处理
            std::cout << "ListMultipartUploads failed." << output.error().String() << std::endl;
            // 释放网络等资源
            CloseClient();
            return -1;
        }
        nextKeyMarker = output.result().getNextKeyMarker();
        isTruncated = output.result().isTruncated();

        std::cout << "ListMultipartUploads success." << std::endl;
        for (const auto& part : output.result().getUploads()) {
            abortMultipartUploadInput.setKey(part.getKey());
            abortMultipartUploadInput.setUploadId(part.getUploadId());
            auto abortOutput = client.abortMultipartUpload(abortMultipartUploadInput);
            if (!abortOutput.isSuccess()){
                std::cout << "DeletePart failed:" << abortOutput.error().String() << std::endl;
                // 释放网络等资源
                CloseClient();
                return -1;
            }
        }
    }
    // 释放网络等资源
    CloseClient();
    return 0;
}