简述

阿里云对象存储(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 选项
Qt案例-编译阿里云OSS对象存储C++ SDK源码,并进行简单下载,上传数据,显示进度等相关功能-LMLPHP
生成以下文件:
Qt案例-编译阿里云OSS对象存储C++ SDK源码,并进行简单下载,上传数据,显示进度等相关功能-LMLPHP
使用vs打开alibabacloud-oss-cpp-sdk.sln重新生成cpp-sdk
Qt案例-编译阿里云OSS对象存储C++ SDK源码,并进行简单下载,上传数据,显示进度等相关功能-LMLPHP

Qt 添加引用

Qt 调用需要把 SDK中的文件夹放在项目目录下,并添加引用
Qt案例-编译阿里云OSS对象存储C++ SDK源码,并进行简单下载,上传数据,显示进度等相关功能-LMLPHP

# 动态库链接
# /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

同时需要把third_party中的dll添加进去
Qt案例-编译阿里云OSS对象存储C++ SDK源码,并进行简单下载,上传数据,显示进度等相关功能-LMLPHP

//注意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

常用 Endpoint

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

#include <alibabacloud/oss/OssClient.h>
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;
}

使用方法

OSS C++ SDK提供丰富的示例代码
在OSS C++ SDk中ObjectSample.h文件提供了大多数方法的调用示例,
Qt案例-编译阿里云OSS对象存储C++ SDK源码,并进行简单下载,上传数据,显示进度等相关功能-LMLPHP
如:
Qt案例-编译阿里云OSS对象存储C++ SDK源码,并进行简单下载,上传数据,显示进度等相关功能-LMLPHP

上传示例:

//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());
}

直接读取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();

进度下载:

当通过线程进行下载时注意 通过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());
   }
}

测试时遇到的两个问题

添加<windows.h>头文件时无法识别外部链接GetObjectW

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

#include <Windows.h>
#undef GetObject
#undef GetObjectW
#undef GetObjectA

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

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

当测试下载进度时,需要ProgressCallback方法中发送信号,而ProgressCallback方法是个静态方法,解决方法是在ProgressCallback中调用个单例类来单独发送信息,而这个单例类线程类绑定信号;下载的暂停同样是在ProgressCallback中实现。
Qt案例-编译阿里云OSS对象存储C++ SDK源码,并进行简单下载,上传数据,显示进度等相关功能-LMLPHP

09-10 09:16