You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:12:15