帮助与文档

我们为你提供丰富、详尽的使用指南以及产品文档

快速指南

在开始使用 SDK 之前,请确认您已经了解 青云 QingStor 对象存储基本概念 ,如 Zone,Service,Bucket,Object 等。

准备工作

快速开始

使用 SDK 之前请先在 青云控制台 申请 access key 。

配置文件

在使用 SDK 之前,我们需要创建一个本地的配置文件。也可以在初始化 SDK 时通过 QsConfig::LoadConfigFile() 方法来指定具体的配置文件路径。

配置文件同时支持 hostport 等参数的配置,只需要添加对应配置项即可,全部的可配置项如下:

    access_key_id: 'ACCESS_KEY_ID_EXAMPLE'
    secret_access_key: 'SECRET_ACCESS_KEY_EXAMPLE'
    host: 'qingstor.com'
    port: 443
    protocol: 'https'
    connection_retries: 3
    timeOutPeriod: 3

代码片段

初始化 SDK

在使用 SDK 之前,需要先初始化全局资源,同时通过一些全局配置参数,指定 SDK 相关的设置:

    // 由入参分别指定 SDK 输出日志的路径、日志级别、 SDK 的 init 过程和 shutdown 过程是否自动初始化和清理 curl 库的全局资源。
    // 其中,有效的日志级别为 None, Fatal, Error, Warning, Info, Debug, Verbose ,默认日志级别为 None ,即不输出日志。
    // 如果在程序中的另外的模块使用了 curl 库,QingStor SDK 自动初始化和清理 curl 库的全局资源,可能会引起这些模块功能产生异常。
    // 这种情况下如果你希望统一管理 curl 全局资源的初始化及清理工作,请将参数设置为 0 ,否则请设置成 1 .
    QingStor::SDKOptions sdkOptions;
    sdkOptions.logLevel = LogLevel::Verbose;
    sdkOptions.logPath = "/tmp/";
    sdkOptions.initAndCleanupCurl = true;

    QingStor::InitializeSDK(sdkOptions);

调用 SDK 接口前,需要先指定访问的 Bucket 和 Zone 信息,创建访问句柄。 你有两种创建访问句柄的方式:

1.你可以通过指定配置文件地址,来创建访问句柄。

    QingStor::QsConfig qsConfig;
    qsConfig.LoadConfigFile("/etc/qingstor/config.yaml");

    context->pQsService = new QingStorService(qsConfig);
    context->pQsBucket = new Bucket(qsConfig, "yourbucketname", "yourzone");

2.你也可以通过指定 config 结构,设置具体 config 参数,来创建访问句柄。

    QingStor::QsConfig qsConfig;

    // 你可以指定协议类型,请求重试的次数, 以及每次请求超时时间 等配置
    qsConfig.access_key_id = "ACCESS_KEY_ID";
    qsConfig.secret_access_key = "SECRET_ACCESS_KEY";
    qsConfig.protocol = "https";
    qsConfig.conn_retries = 3;
    qsConfig.timeout_period = 10;

    // 在私有云环境中,你可以指定实际配置的 host 地址 和服务端口
    // 访问 QingStor 公有云服务, 通常无需更改 host 地址 和服务端口.
    qsConfig.host = "api.private.com";
    qsConfig.port = 4433;

    context->pQsService = new QingStorService(qsConfig);
    context->pQsBucket = new Bucket(qsConfig, strBucketName, strZone);

获取账户下的 Bucket 列表

之前我们创建了一个 Bucket ,接下来我们将会示范如何获取账户下所有 Buckets。

    ListBucketsInput input;
    ListBucketsOutput output;

    QsError err = qsBucket.ListObjects(input, output);
    if (QsError::QS_ERR_NO_ERROR == err)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        printf("Got response code : %s",output.GetResponseCode());
    }

    if (QsError::QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

上传一个 Object

接下来我们将会演示如何在 Bucket 中上传一个 Object:

    PutObjectInput input;
    PutObjectOutput output;

    // object 的内容可以来自于文件 (filestream),可以来自于其他形式的 stream ,只需要保证其为 iostream 的子类.
    std::iostream * = new objectStream(new std::fstream("/tmp/Screenshot.jpg"));
    objectStream->seekg(0, objectStream->end);
    auto streamSize = objectStream->tellg();
    objectStream->seekg(0, objectStream->beg);
    input.SetBody(objectStream);
    input.SetContentLength(streamSize);

    QsError err = qsBucket.PutObject(objectKey, input, output);
    if (QsError::QS_ERR_NO_ERROR != err)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        printf("Got response code : %s",output.GetResponseCode());
    }

    if (QsError::QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        ResponseErrorInfo  errorInfo = output.GetResponseErrInfo();
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

    // 释放资源
    if(objectStream)
        delete objectStream;

列出 Bucket 中的 Objects

    ListObjectsInput input;
    ListObjectsOutput output;

    // 设置 response 中返回 object 的数量限制
    input.SetLimit(200);

    QsError err = qsBucket.ListObjects(input, output);
    if (QsError::QS_ERR_NO_ERROR == err)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        std::vector<KeyType> keys = output.GetKeys();
        printf("Got %d objects\n" ,keys.size());
    }

    if (QsError::QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        ResponseErrorInfo  errorInfo = output.GetResponseErrInfo();
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

删除一个 Object

    DeleteObjectInput input;
    DeleteObjectOutput output;

    QsError err = qsBucket.DeleteObject(objectkey, input, output);
    if (QsError::QS_ERR_NO_ERROR != err)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        printf("Got response code : %s",output.GetResponseCode());
    }

    if (QsError::QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        ResponseErrorInfo  errorInfo = output.GetResponseErrInfo();
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

查看一个 Object 的状态

    HeadObjectInput input;
    HeadObjectOutput output;

    QsError err = qsBucket.HeadObject(objectkey, input, output);
    if (QS_ERR_NO_ERROR != err)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        printf("Got response code : %s",output.GetResponseCode());
    }

    if (QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        ResponseErrorInfo  errorInfo = output.GetResponseErrInfo();
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

初始化一个分段上传

    initiateMultipartUpload input;
    initiateMultipartUpload output;

    QsError err = qsBucket.InitiateMultipartUpload(objectkey, input, output);
    if (QsError::QS_ERR_NO_ERROR == err)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        printf("Got response code : %s",output.GetResponseCode());

        // 获取 Upload ID , 假设此处为 "9d37dd6ccee643075ca4e597ad65655c"
        printf("The upload id is : %s",output.GetUploadID());
    }

    if (QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

上传一个分段

    // 上传第1个分段
    UploadMultipartInput inputPart1;
    UploadMultipartOutput outputPart1;

    // object 的内容可以是任何形式的 stream,只需要保证其为 iostream 的子类, 分段最小为 4MB,每个分段最大为 5GB
    std::iostream* objectStream1 = new std::fstream(filePath1));
    objectStream1->seekg(0, objectStream1->end);
    size_t streamSize1 = objectStream1->tellg();
    objectStream1->seekg(0, objectStream1->beg);
    inputPart1.SetBody(objectStream1);
    inputPart1.SetContentLength(streamSize1);
    inputPart1.SetPartNumber(1);
    inputPart1.SetUploadID("9d37dd6ccee643075ca4e597ad65655c");
    QsError err1 = qsBucket.UploadMultipart(objectkey, inputPart1, outputPart1);
    if (QsError::QS_ERR_NO_ERROR == err1)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        printf("Got response code : %s",output.GetResponseCode());
    }

    if (QsError::QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

    // 释放资源
    if(objectStream1)
        delete objectStream1;

    // 上传第2个分段
    UploadMultipartInput inputPart2;
    UploadMultipartOutput outputPart2;

    // object 的内容可以是任何形式的 stream,只需要保证其为 iostream 的子类, 分段最小为 4MB,每个分段最大为 5GB
    std::iostream* objectStream2 = new std::fstream(filePath2));
    objectStream2->seekg(0, objectStream2->end);
    size_t streamSize2 = objectStream2->tellg();
    objectStream2->seekg(0, objectStream2->beg);
    inputPart2.SetBody(objectStream2);
    inputPart2.SetContentLength(streamSize2);
    inputPart2.SetPartNumber(2);
    inputPart2.SetUploadID("9d37dd6ccee643075ca4e597ad65655c");

    QsError err2 = qsBucket.UploadMultipart(objectkey, inputPart2, outputPart2);
    if (QsError::QS_ERR_NO_ERROR == err2)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        printf("Got response code : %s",output.GetResponseCode());
    }

    if (QsError::QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

    // 释放资源
    if(objectStream2)
        delete objectStream2;

列出已经上传的分段

    ListMultipartInput input;
    ListMultipartOutput output;

    input.SetUploadID("9d37dd6ccee643075ca4e597ad65655c");
    std::vector < ObjectPartType > objectParts;

    QsError err = qsBucket.ListMultipart (objectkey, input, output);
    if (QS_ERR_NO_ERROR != err)
    {
        objectParts = output.GetObjectParts();
        printf(Got "%d object parts\n",objectParts.size());
    }

    if (QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

完成一个分段上传

    CompleteMultipartUploadInput input;
    CompleteMultipartUploadOutput output;

    // 设置确认完成合并的 part 列表
    std::vector<ObjectPartType> objectParts;
    ObjectPartType part1,part2;
    part1.SetPartNumber(1);
    part2.SetPartNumber(2);
    objectParts.push_back(part1);
    objectParts.push_back(part2);

    input.SetUploadID ("9d37dd6ccee643075ca4e597ad65655c");
    input.SetObjectParts(objectParts);

    QsError err = qsBucket.CompleteMultipartUpload (objectkey, input, output);
    if (QS_ERR_NO_ERROR != err)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        printf("Got response code : %s",output.GetResponseCode());
    }

    if (QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

取消一个分段上传

    AbortMultipartUploadInput input;
    AbortMultipartUploadOutput output;

    // 设置要取消的 Upload ID,对应的所有已上传分段会被删除
    input.SetUploadID("9d37dd6ccee643075ca4e597ad65655c");

    QsError err = qsBucket.abortMultipartUpload(objectkey, input, output);
    if (QS_ERR_NO_ERROR != err)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        printf("Got response code : %s",output.GetResponseCode());
    }

    if (QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

获取 Bucket 的访问控制列表

QingStor 对象存储支持存储空间访问控制列表 (Bucket ACL), 为存储空间级别的访问控制,用户可将存储空间的读、写、或读写权限开放给单个或多个 QingCloud 用户。下面我们将会演示如何通过 API 接口来获取和设置 Bucket ACL。

    GetBucketACLInput input;
    GetBucketACLOutput output;

    QsError err = qsBucket.GetBucketACL(input, output);
    if (QS_ERR_NO_ERROR != err)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        if (contextOutput->GetACL().size())
        {
            std::string granteeName = contextOutput->GetACL().at(1).GetGrantee().GetName();
            printf("The first ACL Grantee Name is : %s",granteeName.c_str());
        }
    }

    if (QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

设置 Bucket 的访问控制列表

    PutBucketACLInput input;
    PutBucketACLOutput output;

    // 设置 ACL 列表
    std::vector<ACLType> aclList;
    ACLType acl;
    GranteeType grantee;
    grantee.SetType("group");
    grantee.SetName("QS_ALL_USERS");
    acl.SetGrantee(grantee);
    acl.SetPermission("FULL_CONTROL");
    aclList.push_back(acl);
    input.SetACL(aclList);

    QsError err = qsBucket.PutBucketACL(input, output);
    if (QS_ERR_NO_ERROR != err)
    {
        // 当返回值为 QS_ERR_NO_ERROR 时,代表得到了符合预期的 response ,可以使用 output 中的信息完成你需要的业务逻辑
        printf("Got response code : %s",output.GetResponseCode());
    }

    if (QS_ERR_UNEXCEPTED_RESPONSE == err)
    {
        // 当返回值为 QS_ERR_UNEXCEPTED_RESPONSE 时,代表得到了不符合预期的 response,可以进一步判定错误描述细节
        printf("request_id = %s , %s\n" , errorInfo.requestID.c_str(), errorInfo.message.c_str());
    }

更多操作

所有的 API 调用接口均与上面的示例相似,您可以访问 青云 QingStor 对象存储 API 文档 来了解更多讯息。