aws-sdk-cpp 库:在 C++ 中集成 S3 和云存储
现代 C++ 应用程序越来越需要与云存储进行交互。无论是备份、存储媒体文件还是在服务之间交换数据——S3 兼容存储(Amazon S3、MinIO、Yandex Object Storage、DigitalOcean Spaces)已成为事实上的标准。Amazon 的官方库 aws-sdk-cpp 提供了强大而灵活的工具集,可直接从 C++ 代码中操作 S3。
在本文中,我们将介绍如何连接 aws-sdk-cpp、配置身份验证、执行基本的对象和存储桶操作,并探讨与兼容存储配合使用的注意事项。
什么是 aws-sdk-cpp?
aws-sdk-cpp 是 Amazon Web Services 为 C++ 语言提供的官方 SDK。它包含所有主要 AWS 服务的模块,包括 S3、DynamoDB、Lambda、EC2 等。用于云存储的 S3 模块支持:
- 创建、删除和列出存储桶(buckets)。
- 上传、下载、复制和删除对象。
- 对大文件进行分段上传(multipart upload)。
- 管理元数据和 ACL(访问控制列表)。
- 支持流式数据传输和异步操作。
安装与配置
安装 SDK 最简单的方法是通过包管理器 vcpkg:
vcpkg install aws-sdk-cpp[s3]如需从源码手动构建,则需要 CMake 和支持 C++14 或更高版本的编译器。安装后,在 CMakeLists.txt 中链接库:
find_package(aws-sdk-cpp REQUIRED COMPONENTS s3 s3-crt)target_link_libraries(your_project PRIVATE AWS::aws-cpp-sdk-s3 AWS::aws-cpp-sdk-s3-crt)注意:s3-crt 是基于 Common Runtime 的替代实现,可为流式操作提供更好的性能。
配置 S3 客户端
开始之前,需要创建 Aws::S3::S3Client 对象。要访问兼容存储(例如 MinIO 或 Yandex Object Storage),需要指定自定义 endpoint:
#include <aws/core/Aws.h>#include <aws/s3/S3Client.h>#include <aws/s3/model/ListObjectsV2Request.h>
Aws::SDKOptions options;Aws::InitAPI(options);{ Aws::Client::ClientConfiguration config; config.endpointOverride = "https://storage.yandexcloud.net"; // 用于 Yandex Object Storage config.region = "ru-central1"; config.scheme = Aws::Http::Scheme::HTTPS;
// 对于本地 MinIO:config.endpointOverride = "http://localhost:9000"; // config.region = "us-east-1"; // MinIO 默认使用此区域
Aws::Auth::AWSCredentials credentials("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY"); Aws::S3::S3Client s3_client(credentials, config);
// 接下来使用客户端进行操作}Aws::ShutdownAPI(options);示例:将文件上传到 S3
我们来看一个基本操作——将本地文件上传到存储桶:
#include <aws/s3/model/PutObjectRequest.h>#include <fstream>
bool UploadFile(const Aws::S3::S3Client& client, const std::string& bucket_name, const std::string& object_key, const std::string& file_path){ Aws::S3::Model::PutObjectRequest request; request.SetBucket(bucket_name); request.SetKey(object_key);
std::shared_ptr<Aws::IOStream> input_data = Aws::MakeShared<Aws::FStream>("UploadFile", file_path.c_str(), std::ios_base::in | std::ios_base::binary);
if (!input_data->good())\