如何使用AWS C++ SDK实现S3分段上传?求技术方向指引
我太懂这种找不到对应SDK示例的抓狂了——AWS C++ SDK的S3分段上传文档确实不如Java、.NET那些直观,但其实核心流程和其他SDK是一致的,我给你梳理下完整的实现思路和关键代码片段,你可以直接参考:
核心实现流程
1. 初始化AWS SDK和S3客户端
首先要完成SDK的初始化,创建一个配置好区域和凭证的S3客户端实例:
#include <aws/core/Aws.h> #include <aws/s3/S3Client.h> #include <aws/s3/model/CreateMultipartUploadRequest.h> #include <aws/s3/model/UploadPartRequest.h> #include <aws/s3/model/CompleteMultipartUploadRequest.h> #include <aws/s3/model/CompletedMultipartUpload.h> #include <aws/s3/model/CompletedPart.h> #include <fstream> #include <vector> #include <iostream> int main() { // 初始化AWS SDK Aws::SDKOptions options; Aws::InitAPI(options); { // 配置客户端参数,替换成你的区域 Aws::Client::ClientConfiguration config; config.region = "us-east-1"; // 创建S3客户端,默认会读取环境变量、凭证文件等配置的凭证 Aws::S3::S3Client s3_client(config); // 后续的分段上传逻辑都写在这里 } // 关闭SDK Aws::ShutdownAPI(options); return 0; }
2. 启动分段上传会话
调用CreateMultipartUpload接口获取唯一的UploadId,这个ID是后续所有分段上传的标识:
const Aws::String bucket_name = "your-target-bucket"; const Aws::String object_key = "your-object-key-in-s3"; Aws::S3::Model::CreateMultipartUploadRequest create_req; create_req.SetBucket(bucket_name); create_req.SetKey(object_key); auto create_outcome = s3_client.CreateMultipartUpload(create_req); if (!create_outcome.IsSuccess()) { std::cerr << "Failed to start multipart upload: " << create_outcome.GetError().GetMessage() << std::endl; return 1; } // 保存这个UploadId,后续所有步骤都需要它 const Aws::String upload_id = create_outcome.GetResult().GetUploadId();
3. 拆分文件并上传分段
把本地文件拆分成多个分段(建议每个分段5MB以上,最后一个分段可以更小),逐个上传并记录每个分段的ETag(后续完成上传需要用到):
const std::string local_file_path = "/path/to/your/large/file"; std::ifstream file_stream(local_file_path, std::ios::binary | std::ios::ate); if (!file_stream.is_open()) { std::cerr << "Failed to open local file: " << local_file_path << std::endl; // 出错要主动终止上传,避免产生无效分段费用 Aws::S3::Model::AbortMultipartUploadRequest abort_req; abort_req.SetBucket(bucket_name); abort_req.SetKey(object_key); abort_req.SetUploadId(upload_id); s3_client.AbortMultipartUpload(abort_req); return 1; } // 获取文件总大小 const std::streampos file_size = file_stream.tellg(); // 设置分段大小为5MB,你可以根据需求调整 const size_t part_size = 5 * 1024 * 1024; // 计算总分段数 size_t total_parts = static_cast<size_t>(file_size / part_size); if (file_size % part_size != 0) { total_parts++; } // 保存已上传成功的分段信息 std::vector<Aws::S3::Model::CompletedPart> completed_parts; for (size_t part_num = 1; part_num <= total_parts; ++part_num) { // 定位到当前分段的起始位置 file_stream.seekg((part_num - 1) * part_size); // 读取分段内容到缓冲区 std::vector<unsigned char> buffer(part_size); file_stream.read(reinterpret_cast<char*>(buffer.data()), part_size); const size_t bytes_read = file_stream.gcount(); // 构造分段上传请求 Aws::S3::Model::UploadPartRequest upload_req; upload_req.SetBucket(bucket_name); upload_req.SetKey(object_key); upload_req.SetUploadId(upload_id); upload_req.SetPartNumber(part_num); // 将读取的文件内容转为流对象作为请求体 upload_req.SetBody(std::make_shared<Aws::StringStream>(std::string(buffer.begin(), buffer.begin() + bytes_read))); // 执行分段上传 auto upload_outcome = s3_client.UploadPart(upload_req); if (!upload_outcome.IsSuccess()) { std::cerr << "Failed to upload part " << part_num << ": " << upload_outcome.GetError().GetMessage() << std::endl; // 上传失败,终止整个会话 Aws::S3::Model::AbortMultipartUploadRequest abort_req; abort_req.SetBucket(bucket_name); abort_req.SetKey(object_key); abort_req.SetUploadId(upload_id); s3_client.AbortMultipartUpload(abort_req); return 1; } // 记录成功上传的分段信息 Aws::S3::Model::CompletedPart completed_part; completed_part.SetPartNumber(part_num); completed_part.SetETag(upload_outcome.GetResult().GetETag()); completed_parts.push_back(completed_part); }
4. 完成分段上传
所有分段上传成功后,调用CompleteMultipartUpload接口把所有分段合并成一个完整的S3对象:
Aws::S3::Model::CompletedMultipartUpload completed_upload; completed_upload.SetParts(completed_parts); Aws::S3::Model::CompleteMultipartUploadRequest complete_req; complete_req.SetBucket(bucket_name); complete_req.SetKey(object_key); complete_req.SetUploadId(upload_id); complete_req.SetMultipartUpload(completed_upload); auto complete_outcome = s3_client.CompleteMultipartUpload(complete_req); if (!complete_outcome.IsSuccess()) { std::cerr << "Failed to complete multipart upload: " << complete_outcome.GetError().GetMessage() << std::endl; // 失败也要终止会话 Aws::S3::Model::AbortMultipartUploadRequest abort_req; abort_req.SetBucket(bucket_name); abort_req.SetKey(object_key); abort_req.SetUploadId(upload_id); s3_client.AbortMultipartUpload(abort_req); return 1; } std::cout << "Multipart upload finished successfully! Object URL: " << complete_outcome.GetResult().GetLocation() << std::endl;
关键注意事项
- 分段大小要求:除最后一个分段外,其他分段必须至少5MB,否则AWS会拒绝请求。
- 异常处理:任何步骤失败都要调用
AbortMultipartUpload,未完成的分段会在S3中保留7天,期间会产生存储费用,主动清理更稳妥。 - 凭证配置:如果本地测试没有默认凭证(比如未配置
~/.aws/credentials),可以在ClientConfiguration中手动指定凭证提供者,比如环境变量凭证:config.credentials = Aws::MakeShared<Aws::Auth::EnvironmentAWSCredentialsProvider>(""); - 性能优化:超大文件可以用多线程并行上传分段,但要注意S3客户端的线程安全(AWS C++ SDK的S3客户端是线程安全的,可以在多线程中复用)。
内容的提问来源于stack exchange,提问作者Sudheer Kumar
相关产品推荐
相关产品推荐

