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

追加上传(C++ SDK)

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

首次发布时间2022.04.08 10:56:30

追加上传创建的对象类型为追加类型 (Appendable Object) ,可在对象末尾追加写入数据。而普通上传和分片上传创建的对象类型为普通类型 (Normal Object),无法追加写入数据。

注意事项

  • 追加上传对象前,您必须具有 tos:PutObject 权限,具体操作请参见权限配置指南
  • 上传对象时,对象名必须满足一定规范,详细信息请参见对象命名规范
  • TOS 是面向海量存储设计的分布式对象存储产品,内部分区存储了对象索引数据,为横向扩展您上传对象和下载对象时的最大吞吐量,和减小热点分区的概率,请您避免使用字典序递增的对象命名方式,详细信息,请参见性能优化
  • 如果桶中已经存在同名对象,则新对象会覆盖已有的对象。桶开启多版本的场景下,则会保留原有对象,生成一个新版本号用于标识新上传的对象。
  • 追加上传对象不支持 Chunk-Encoded 的请求方式,当您追加上传网络流时请迭代获取数据再追加上传。

追加上传限制

使用 appendObject 接口时,对象的大小限制说明如下:

  • 每次追加的大小不能小于 128KiB,追加后的对象大小不能大于 5GiB。
  • 通过 appendObject 创建的对象,进行 putObject 操作,对象被覆盖且对象类型由 Appendable 变为 Normal。反之通过 putObject 上传的对象不支持追加写操作。
  • appendObject 创建的对象不支持拷贝。
  • 如果对象类型为低频存储或归档闪回存储,则无法使用 appendObject 接口。
  • 如果您的存储桶处于开启或暂停多版本控制功能的状态下,则无法使用 appendObject 接口。

示例代码

从内存中追加上传

以下代码用于将内存中的字符串追加上传到目标桶 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";
    
    // 初始化网络等资源
    InitializeClient();
    // 创建交互的 client
    TosClientV2 client(region, accessKey, secretKey);

    // 第一次追加的位置是0,返回值为下一次追加的位置。后续追加的位置是追加前文件的长度。
    auto part0 = std::make_shared<std::stringstream>();
    for (int i = 0; i < (128 << 10); ++i) {
        *part0 << "1";
    }
    AppendObjectV2Input input(bucketName, objectName, part0, 0);
    auto output = client.appendObject(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "AppendObject failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "AppendObject success." << std::endl;
    std::cout << "Next Append Offset is: " << output.result().getNextAppendOffset() << std::endl;
    std::cout << "Pre HashCrc64Ecma is: " << output.result().getHashCrc64ecma() << std::endl;


    auto part1 = std::make_shared<std::stringstream>();
    for (int i = 0; i < (256 << 10); ++i) {
        *part1 << "1";
    }
    input.setContent(part1);
    // 从第一次追加的返回结果中,获取后续追加的位置offset和用于计算Crc64的PreHashCrc64Ecma
    input.setOffset(output.result().getNextAppendOffset());
    input.setPreHashCrc64Ecma(output.result().getHashCrc64ecma());
    auto output1 = client.appendObject(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "AppendObject failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "AppendObject success." << std::endl;
    std::cout << "Next Append Offset is: " << output1.result().getNextAppendOffset() << std::endl;
    std::cout << "Pre HashCrc64Ecma is: " << output1.result().getHashCrc64ecma() << 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";

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

    // 第一次追加的位置是0,返回值为下一次追加的位置。后续追加的位置是追加前文件的长度。
    auto part0 = std::make_shared<std::stringstream>();
    for (int i = 0; i < (128 << 10); ++i) {
        *part0 << "1";
    }
    AppendObjectV2Input input(bucketName, objectName, part0, 0);

    // 设置进度条
    DataTransferListener datatransferlistener = {ProgressCallback, nullptr};
    input.setDataTransferListener(datatransferlistener);

    auto output = client.appendObject(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "AppendObject failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "AppendObject success." << std::endl;
    std::cout << "Next Append Offset is: " << output.result().getNextAppendOffset() << std::endl;
    std::cout << "Pre HashCrc64Ecma is: " << output.result().getHashCrc64ecma() << std::endl;


    auto part1 = std::make_shared<std::stringstream>();
    for (int i = 0; i < (256 << 10); ++i) {
        *part1 << "1";
    }
    input.setContent(part1);
    // 从第一次追加的返回结果中,获取后续追加的位置offset和用于计算Crc64的PreHashCrc64Ecma
    input.setOffset(output.result().getNextAppendOffset());
    input.setPreHashCrc64Ecma(output.result().getHashCrc64ecma());
    auto output1 = client.appendObject(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "AppendObject failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "AppendObject success." << std::endl;
    std::cout << "Next Append Offset is: " << output1.result().getNextAppendOffset() << std::endl;
    std::cout << "Pre HashCrc64Ecma is: " << output1.result().getHashCrc64ecma() << 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";

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

    // 第一次追加的位置是0,返回值为下一次追加的位置。后续追加的位置是追加前文件的长度。
    auto part0 = std::make_shared<std::stringstream>();
    for (int i = 0; i < (128 << 10); ++i) {
        *part0 << "1";
    }
    AppendObjectV2Input input(bucketName, objectName, part0, 0);

    // 设置客户端限速
    std::shared_ptr<RateLimiter> RateLimiter(NewRateLimiter(1024 * 1024, 1024 * 1024));
    input.setRateLimiter(RateLimiter);

    auto output = client.appendObject(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "AppendObject failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "AppendObject success." << std::endl;
    std::cout << "Next Append Offset is: " << output.result().getNextAppendOffset() << std::endl;
    std::cout << "Pre HashCrc64Ecma is: " << output.result().getHashCrc64ecma() << std::endl;


    auto part1 = std::make_shared<std::stringstream>();
    for (int i = 0; i < (256 << 10); ++i) {
        *part1 << "1";
    }
    input.setContent(part1);
    // 从第一次追加的返回结果中,获取后续追加的位置offset和用于计算Crc64的PreHashCrc64Ecma
    input.setOffset(output.result().getNextAppendOffset());
    input.setPreHashCrc64Ecma(output.result().getHashCrc64ecma());
    auto output1 = client.appendObject(input);
    if (!output.isSuccess()) {
        // 异常处理
        std::cout << "AppendObject failed." << output.error().String() << std::endl;
        // 释放网络等资源
        CloseClient();
        return -1;
    }
    std::cout << "AppendObject success." << std::endl;
    std::cout << "Next Append Offset is: " << output1.result().getNextAppendOffset() << std::endl;
    std::cout << "Pre HashCrc64Ecma is: " << output1.result().getHashCrc64ecma() << std::endl;

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

相关文档

关于追加上传的 API 文档,请参见 AppendObject