• Qt案例-编译阿里云OSS对象存储C++ SDK源码,并进行简单下载,上传数据,显示进度等相关功能


    项目中用到了阿里云OSS对象存储来保存数据,由于以前没用过这个库,就下载了C++版的sdk源码重新编译了一次,并使用Qt调用;不得不说这可能是我编译源码最轻松的一次。

    简述

    阿里云对象存储(Object Storage Service,简称OSS),是阿里云对外提供的海量、安全、低成本、高可靠的云存储服务。用户可以通过调用API,在任何应用、任何时间、任何地点上传和下载数据,也可以通过用户Web控制台对数据进行简单的管理。OSS适合存放任意文件类型,适合各种网站、开发企业及开发者使用。

    适用于阿里云OSS的 C++ SDK提供了一组现代化的 C++(C++ 11)接口,让您不用复杂编程即可访问阿里云OSS服务。

    如果您在使用SDK的过程中遇到任何问题,欢迎前往阿里云SDK问答社区提问,提问前请阅读提问引导:

    阿里云OSS C++工具套件

    直接下载C++版SDK

    通过GitHub下载

    OSS图形化管理工具

    ossbrowser是阿里云官方提供的OSS图形化管理工具,提供类似Windows资源管理器的功能
    OSS图形化管理工具 直接下载【oss-browser-win32-x64】

    阿里云产品文档-安装并登录ossbrowser

    编译源码

    OSS的SDK只有少数的几个配置项,直接默认生成就行,如果需要配置,可以查看 CMAKE 选项
    在这里插入图片描述
    生成以下文件:
    在这里插入图片描述
    使用vs打开alibabacloud-oss-cpp-sdk.sln重新生成cpp-sdk
    在这里插入图片描述

    Qt 添加引用

    Qt 调用需要把 SDK中的文件夹放在项目目录下,并添加引用
    在这里插入图片描述

    # 动态库链接
    # /OSS/include 路径中oss为新建文件夹
    win32:CONFIG(release, debug|release): LIBS += -L$$PWD/OSS/lib/Release/ -lalibabacloud-oss-cpp-sdk
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/OSS/lib/Debug/ -lalibabacloud-oss-cpp-sdk
    
    INCLUDEPATH += $$PWD/OSS/include
    DEPENDPATH += $$PWD/OSS/include
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    同时需要把third_party中的dll添加进去
    在这里插入图片描述

    //注意64位与32位应选择不同文件夹
    win32:CONFIG(release, debug|release): LIBS += -L$$PWD/OSS/other/x64/ -llibeay32
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/OSS/other/x64/ -llibeay32
    
    win32:CONFIG(release, debug|release): LIBS += -L$$PWD/OSS/other/x64/ -lssleay32
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/OSS/other/x64/ -lssleay32
    
    win32:CONFIG(release, debug|release): LIBS += -L$$PWD/OSS/other/x64/ -llibcurl
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/OSS/other/x64/ -llibcurl
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    常用 Endpoint

    在调用oss库时,看一遍说明文档是必要的,就比如Endpoint 这个参数费半天的劲猜对,才发现有详细说明C++初始化

    #include 
    using namespace AlibabaCloud::OSS;
    
    ///地区
    QMap<QString,QString> Mapdata;
     Mapdata.insert("华东1(杭州)","oss-cn-hangzhou.aliyuncs.com");
     Mapdata.insert("华东2(上海)","oss-cn-shanghai.aliyuncs.com");
     Mapdata.insert("华东5(南京-本地地域)","oss-cn-nanjing.aliyuncs.com");
     Mapdata.insert("华北1(青岛)","oss-cn-qingdao.aliyuncs.com");
     Mapdata.insert("华北2(北京)","oss-cn-beijing.aliyuncs.com");
     Mapdata.insert("华北3(张家口)","oss-cn-zhangjiakou.aliyuncs.com");
     Mapdata.insert("华北5(呼和浩特)","oss-cn-huhehaote.aliyuncs.com");
     Mapdata.insert("华北6(乌兰察布)","oss-cn-wulanchabu.aliyuncs.com");
     Mapdata.insert("华南1(深圳)","oss-cn-shenzhen.aliyuncs.com");
     Mapdata.insert("华南2(河源)","oss-cn-heyuan.aliyuncs.com");
     Mapdata.insert("华南3(广州)","oss-cn-guangzhou.aliyuncs.com");
     Mapdata.insert("西南1(成都)","oss-cn-chengdu.aliyuncs.com");
    
    
    int main(void)
    {
        /* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
        std::string Endpoint = "yourEndpoint";
        /* 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。*/
        std::string AccessKeyId = "yourAccessKeyId";
        std::string AccessKeySecret = "yourAccessKeySecret";
        /* 从STS服务获取的安全令牌(SecurityToken)。*/
        std::string SecurityToken = "yourSecurityToken";
        
        /* 初始化网络等资源。*/
        InitializeSdk();
    
        ClientConfiguration conf;
        OssClient client(Endpoint, AccessKeyId, AccessKeySecret, SecurityToken, conf);  
    
        /* 释放网络等资源。*/
        ShutdownSdk();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    使用方法

    OSS C++ SDK提供丰富的示例代码
    在OSS C++ SDk中ObjectSample.h文件提供了大多数方法的调用示例,
    在这里插入图片描述
    如:
    在这里插入图片描述

    上传示例:

    //PutObjectFromFile()
    qDebug()<<"[__FILE__] "<<__FILE__;
    QFileInfo info("E:\\LOCAL_FTP\\archival-information.xml");
    qDebug()<<info.exists();
    std::shared_ptr<std::iostream> content = std::make_shared<std::fstream>(info.absoluteFilePath().toStdString(), std::ios::in | std::ios::binary);
    PutObjectRequest request(bucket_, info.fileName().toStdString(), content);
    auto outcome = client->PutObject(request);
    if (outcome.isSuccess()) {
        std::cout << __FUNCTION__ << " success, ETag:" << outcome.result().ETag() << std::endl;
    }
    else {
        PrintError(__FUNCTION__, outcome.error());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    直接读取OSS下载缓存,不写入文件:

    // 初始化SDK
    InitializeSdk();
     QString Data_XML="";
     ClientConfiguration conf;
     OssClient* client = new OssClient(OSS_Config::OSS_Endpoint, OSS_Config::OSS_AccessKeyId, OSS_Config::OSS_AccessKeySecret, conf);
     {
         std::shared_ptr<std::stringstream> content = std::make_shared<std::stringstream>();
         GetObjectRequest request(OSS_Config::OSS_Buckets, OSS_Path.toStdString());
         request.setResponseStreamFactory([=](){
             return content;
         });
         auto outcome = client->GetObject(request);
         if (outcome.isSuccess()) {
             Data_XML=QString::fromStdString(content->str());
         }
         else {
             OSS_Config::instance().PrintError(__FUNCTION__, outcome.error());
         }
     }
     // 关闭SDK
     ShutdownSdk();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    进度下载:

    当通过线程进行下载时注意 通过ProgressCallback方法获取下载的进度显示,需要注意的是ProgressCallback方法必须为静态方法,

    static void ProgressCallback(size_t increment, int64_t transfered, int64_t total, void* userData)
    {
        std::cout << "ProgressCallback[" << userData << "] => " <<
                     increment <<" ," << transfered << "," << total << std::endl;
    }
    
    {
       DownloadObjectRequest request(bucket_, "xxx.pdf", Config::FileDownloadTo, "", 100*1024, 0 );
       TransferProgress progressCallback = { ProgressCallback , this };
       request.setTransferProgress(progressCallback);
       auto outcome = client->ResumableDownloadObject(request);
       if (outcome.isSuccess()) {
           std::cout << __FUNCTION__ << "[" << this << "]" << " success, ETag:" << outcome.result().Metadata().ETag() << std::endl;
       }
       else {
           PrintError(__FUNCTION__, outcome.error());
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    测试时遇到的两个问题

    添加头文件时无法识别外部链接GetObjectW

    添加头文件时,会提示无法识别外部链接GetObjectW的问题此时只需要:
    添加3个undef语句,避免了调用OSS::GetObject时编译报错

    #include 
    #undef GetObject
    #undef GetObjectW
    #undef GetObjectA
    
    • 1
    • 2
    • 3
    • 4

    阿里云OSS C++SDK在VS15编译提示无法识别外部链接GetObjectW的解决办法

    在添加进度条下载功能时,静态方法发送信号

    当测试下载进度时,需要ProgressCallback方法中发送信号,而ProgressCallback方法是个静态方法,解决方法是在ProgressCallback中调用个单例类来单独发送信息,而这个单例类线程类绑定信号;下载的暂停同样是在ProgressCallback中实现。
    在这里插入图片描述

  • 相关阅读:
    统计学习方法 决策树
    重装系统后新建文本文档打不开怎么办
    前馈神经网络与支持向量机实战 --- 手写数字识别
    cookies 设置过期时间
    MySQL数据库 #2
    当我们对组件二次封装时我们在封装什么
    gorm-增删改查
    21、嵌套路由实战操作
    Centos7安装go解释器
    【图解RabbitMQ-2】图解JMS规范与AMQP协议是什么
  • 原文地址:https://blog.csdn.net/qq_35554617/article/details/132776539