目前有将服务器指定文件上传的需求, 手头正好有免费的COS资源使用, 于是使用COS作为存储工具
腾讯云COS C SDK 文档如下
https://cloud.tencent.com/document/product/436/12301
本次文件上传流程
基于
- Ubuntu20.04LTS
- CLion 2022.1
建立工程
参照官方SDK的Demo
https://github.com/tencentyun/cos-cpp-sdk-v5
文件上传的CMakeLists.txt
如下
cmake_minimum_required(VERSION 3.5)
project(auto-backup CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function")
set(SYSTEM_LIBS stdc pthread)
include_directories("${CMAKE_SOURCE_DIR}/thirdparty/include")
add_executable(${PROJECT_NAME} main.cc)
# 使用动态库
target_link_libraries(${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/thirdparty/lib/cos/libcossdk-shared.so ${SYSTEM_LIBS})
项目结构如下
代码语言:javascript复制├── cmake-build-debug
│
├── CMakeLists.txt
│
├── main.cc
│
├── oss_config.json
│
└── thirdparty
│
├── include
│ │
│ ├── cos
│ │
│ └── Poco
│
└── lib
│
└── cos
main.cc
内容如下
#include <unistd.h>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <cstring>
#include "cos/cos_api.h"
#include "cos/cos_defines.h"
#include "cos/cos_config.h"
#include "cos/request/object_req.h"
#include "cos/response/object_resp.h"
int main(int argc, char *argv[]) {
// 1. 指定配置文件路径,初始化 CosConfig
qcloud_cos::CosConfig config("../config.json");
qcloud_cos::CosAPI cos(config);
// 2. 构造上传文件的请求
std::string bucket_name = "examplebucket-1250000000"; // 替换为用户的存储桶名,由bucketname-appid 组成,appid必须填入,可以在COS控制台查看存储桶名称。 https://console.cloud.tencent.com/cos5/bucket
std::string object_name = "exampleobject"; //exampleobject 即为对象键(Key),是对象在存储桶中的唯一标识。例如,在对象的访问域名 examplebucket-1250000000.cos.ap-guangzhou.myzijiebao.com/doc/pic.jpg 中,对象键为 doc/pic.jpg,替换为用户指定的对象名。
qcloud_cos::PutObjectByFileReq req(bucket_name, object_name, "/path/to/local/file"); // 替换为用户指定的文件路径
//req.SetXCosStorageClass("STANDARD_IA"); // 默认为STANDARD,可以调用 Set 方法设置存储类型
qcloud_cos::PutObjectByFileResp resp;
// 3. 调用上传文件接口
qcloud_cos::CosResult result = cos.PutObject(req, &resp);
// 4. 处理调用结果
if (result.IsSucc()) {
// 上传文件成功
} else {
// 上传文件失败,可以调用 CosResult 的成员函数输出错误信息,比如 requestID 等
std::cout << "ErrorInfo=" << result.GetErrorInfo() << std::endl;
std::cout << "HttpStatus=" << result.GetHttpStatus() << std::endl;
std::cout << "ErrorCode=" << result.GetErrorCode() << std::endl;
std::cout << "ErrorMsg=" << result.GetErrorMsg() << std::endl;
std::cout << "ResourceAddr=" << result.GetResourceAddr() << std::endl;
std::cout << "XCosRequestId=" << result.GetXCosRequestId() << std::endl;
std::cout << "XCosTraceId=" << result.GetXCosTraceId() << std::endl;
}
}
一开始是使用的官方SDK Demo中提供的库文件, 但编译不通过
报错未定义的引用
比如
undefined reference to `typeinfo for qcloud_cos::BaseResp'
以及
libPocoCrypto.so.64: undefined reference to `EVP_PKEY_set1_RSA@libcrypto.so.10'
查阅文档, 需要自己编译对应依赖
1. 编译Poco
代码语言:javascript复制wget https://github.com/pocoproject/poco/archive/refs/tags/poco-1.9.4-release.zip
cd poco-poco-1.9.4-release/
./configure --omit=Data/ODBC,Data/MySQL
mkdir my_build
cd my_build
cmake ..
make -j5
若编译 poco 库的时候无法编译出 PocoNetSSL 库,一般是因为机器没装 openssl-devel 库, 自行安装后再次编译Poco
编译完成后, 将编译好的poco lib覆盖到third_party的Poco目录下
将Demo中的install-libpoco.sh
文件都加上-f
参数以覆盖之前的操作,
比如
代码语言:javascript复制ln -s -f libPocoCrypto.so.64 libPocoCrypto.so
执行
代码语言:javascript复制sh install-libpoco.sh
Poco库完成
2. 编译COS SDK
修改SDK Demo中的CMakeLists.txt
, 开启编译动态库选项
option(BUILD_SHARED_LIB "Build shared library" ON)
然后 line:46
替换为
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c 11 -Wall -Wextra")
在Demo目录中
代码语言:javascript复制mkdir -p build
cd build
cmake ..
make
编译完成后, 将build/lib
目录下的库文件复制到自己工程
编译启动main.cc
, 查看COS面板, 文件上传成功
完成
上传COS项目源码
https://github.com/MQPearth/auto-backup
番外
静态链接
- 编译静态Poco库
Poco/CMakeLists.txt
line:118
改为ON
option(POCO_STATIC
"Set to OFF|ON (default is OFF) to control build of POCO as STATIC library" ON)
然后重复之前步骤
然后将编译后的.a
库文件复制到自己项目的lib/Poco目录里
修改自己项目的CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(auto-backup CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function")
set(SYSTEM_LIBS stdc pthread)
set(CMAKE_EXE_LINKER_FLAGS "-static")
include_directories("${CMAKE_SOURCE_DIR}/thirdparty/include")
add_executable(${PROJECT_NAME} main.cc)
# 链接 openssl 静态库
find_library(SSL_LIB libssl.a REQUIRED)
find_library(CRYPTO_LIB libcrypto.a REQUIRED)
target_link_libraries(${PROJECT_NAME}
${CMAKE_SOURCE_DIR}/thirdparty/lib/cos/libcossdk.a
-Wl,--start-group
${CMAKE_SOURCE_DIR}/thirdparty/lib/Poco/libPocoNetSSL.a
${SSL_LIB}
${CRYPTO_LIB}
${CMAKE_DL_LIBS}
${CMAKE_SOURCE_DIR}/thirdparty/lib/Poco/libPocoCrypto.a
${CMAKE_SOURCE_DIR}/thirdparty/lib/Poco/libPocoNet.a
${CMAKE_SOURCE_DIR}/thirdparty/lib/Poco/libPocoJSON.a
${CMAKE_SOURCE_DIR}/thirdparty/lib/Poco/libPocoFoundation.a
${CMAKE_SOURCE_DIR}/thirdparty/lib/Poco/libPocoUtil.a
${CMAKE_SOURCE_DIR}/thirdparty/lib/Poco/libPocoXML.a
-Wl,--end-group
${SYSTEM_LIBS})
然后重新cmake && make
可以看到生成的文件足足有52.3M
, 不过好处就是只有一个文件, 不需要再编译动态库