Amazon S3 examples using SDK for C++ - AWS SDK Code Examples

There are more AWS SDK examples available in the AWS Doc SDK Examples GitHub repo.

Amazon S3 examples using SDK for C++

The following code examples show you how to perform actions and implement common scenarios by using the AWS SDK for C++ with Amazon S3.

Basics are code examples that show you how to perform the essential operations within a service.

Actions are code excerpts from larger programs and must be run in context. While actions show you how to call individual service functions, you can see actions in context in their related scenarios.

Scenarios are code examples that show you how to accomplish specific tasks by calling multiple functions within a service or combined with other AWS services.

Each example includes a link to the complete source code, where you can find instructions on how to set up and run the code in context.

Get started

The following code examples show how to get started using Amazon S3.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

Code for the CMakeLists.txt CMake file.

# Set the minimum required version of CMake for this project. cmake_minimum_required(VERSION 3.13) # Set the AWS service components used by this project. set(SERVICE_COMPONENTS s3) # Set this project's name. project("hello_s3") # Set the C++ standard to use to build this target. # At least C++ 11 is required for the AWS SDK for C++. set(CMAKE_CXX_STANDARD 11) # Use the MSVC variable to determine if this is a Windows build. set(WINDOWS_BUILD ${MSVC}) if (WINDOWS_BUILD) # Set the location where CMake can find the installed libraries for the AWS SDK. string(REPLACE ";" "/aws-cpp-sdk-all;" SYSTEM_MODULE_PATH "${CMAKE_SYSTEM_PREFIX_PATH}/aws-cpp-sdk-all") list(APPEND CMAKE_PREFIX_PATH ${SYSTEM_MODULE_PATH}) endif () # Find the AWS SDK for C++ package. find_package(AWSSDK REQUIRED COMPONENTS ${SERVICE_COMPONENTS}) if (WINDOWS_BUILD AND AWSSDK_INSTALL_AS_SHARED_LIBS) # Copy relevant AWS SDK for C++ libraries into the current binary directory for running and debugging. # set(BIN_SUB_DIR "/Debug") # if you are building from the command line you may need to uncomment this # and set the proper subdirectory to the executables' location. AWSSDK_CPY_DYN_LIBS(SERVICE_COMPONENTS "" ${CMAKE_CURRENT_BINARY_DIR}${BIN_SUB_DIR}) endif () add_executable(${PROJECT_NAME} hello_s3.cpp) target_link_libraries(${PROJECT_NAME} ${AWSSDK_LINK_LIBRARIES})

Code for the hello_s3.cpp source file.

#include <aws/core/Aws.h> #include <aws/s3/S3Client.h> #include <iostream> #include <aws/core/auth/AWSCredentialsProviderChain.h> using namespace Aws; using namespace Aws::Auth; /* * A "Hello S3" starter application which initializes an Amazon Simple Storage Service (Amazon S3) client * and lists the Amazon S3 buckets in the selected region. * * main function * * Usage: 'hello_s3' * */ int main(int argc, char **argv) { Aws::SDKOptions options; // Optionally change the log level for debugging. // options.loggingOptions.logLevel = Utils::Logging::LogLevel::Debug; Aws::InitAPI(options); // Should only be called once. int result = 0; { Aws::Client::ClientConfiguration clientConfig; // Optional: Set to the AWS Region (overrides config file). // clientConfig.region = "us-east-1"; // You don't normally have to test that you are authenticated. But the S3 service permits anonymous requests, thus the s3Client will return "success" and 0 buckets even if you are unauthenticated, which can be confusing to a new user. auto provider = Aws::MakeShared<DefaultAWSCredentialsProviderChain>("alloc-tag"); auto creds = provider->GetAWSCredentials(); if (creds.IsEmpty()) { std::cerr << "Failed authentication" << std::endl; } Aws::S3::S3Client s3Client(clientConfig); auto outcome = s3Client.ListBuckets(); if (!outcome.IsSuccess()) { std::cerr << "Failed with error: " << outcome.GetError() << std::endl; result = 1; } else { std::cout << "Found " << outcome.GetResult().GetBuckets().size() << " buckets\n"; for (auto &bucket: outcome.GetResult().GetBuckets()) { std::cout << bucket.GetName() << std::endl; } } } Aws::ShutdownAPI(options); // Should only be called once. return result; }
  • For API details, see ListBuckets in AWS SDK for C++ API Reference.

Basics

The following code example shows how to:

  • Create a bucket and upload a file to it.

  • Download an object from a bucket.

  • Copy an object to a subfolder in a bucket.

  • List the objects in a bucket.

  • Delete the bucket objects and the bucket.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

#include <iostream> #include <aws/core/Aws.h> #include <aws/s3/S3Client.h> #include <aws/s3/model/CopyObjectRequest.h> #include <aws/s3/model/CreateBucketRequest.h> #include <aws/s3/model/DeleteBucketRequest.h> #include <aws/s3/model/DeleteObjectRequest.h> #include <aws/s3/model/GetObjectRequest.h> #include <aws/s3/model/ListObjectsV2Request.h> #include <aws/s3/model/PutObjectRequest.h> #include <aws/s3/model/BucketLocationConstraint.h> #include <aws/s3/model/CreateBucketConfiguration.h> #include <aws/core/utils/UUID.h> #include <aws/core/utils/StringUtils.h> #include <aws/core/utils/memory/stl/AWSAllocator.h> #include <fstream> #include "s3_examples.h" namespace AwsDoc { namespace S3 { //! Delete an S3 bucket. /*! \param bucketName: The S3 bucket's name. \param client: An S3 client. \return bool: Function succeeded. */ static bool deleteBucket(const Aws::String &bucketName, Aws::S3::S3Client &client); //! Delete an object in an S3 bucket. /*! \param bucketName: The S3 bucket's name. \param key: The key for the object in the S3 bucket. \param client: An S3 client. \return bool: Function succeeded. */ static bool deleteObjectFromBucket(const Aws::String &bucketName, const Aws::String &key, Aws::S3::S3Client &client); } } //! Scenario to create, copy, and delete S3 buckets and objects. /*! \param uploadFilePath: Path to file to upload to an Amazon S3 bucket. \param saveFilePath: Path for saving a downloaded S3 object. \param clientConfig: Aws client configuration. \return bool: Function succeeded. */ bool AwsDoc::S3::S3_GettingStartedScenario(const Aws::String &uploadFilePath, const Aws::String &saveFilePath, const Aws::Client::ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); // Create a unique bucket name which is only temporary and will be deleted. // Format: "amzn-s3-demo-bucket-" + lowercase UUID. Aws::String uuid = Aws::Utils::UUID::RandomUUID(); Aws::String bucketName = "amzn-s3-demo-bucket-" + Aws::Utils::StringUtils::ToLower(uuid.c_str()); // 1. Create a bucket. { Aws::S3::Model::CreateBucketRequest request; request.SetBucket(bucketName); if (clientConfig.region != Aws::Region::US_EAST_1) { Aws::S3::Model::CreateBucketConfiguration createBucketConfiguration; createBucketConfiguration.WithLocationConstraint( Aws::S3::Model::BucketLocationConstraintMapper::GetBucketLocationConstraintForName( clientConfig.region)); request.WithCreateBucketConfiguration(createBucketConfiguration); } Aws::S3::Model::CreateBucketOutcome outcome = client.CreateBucket(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &err = outcome.GetError(); std::cerr << "Error: createBucket: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; return false; } else { std::cout << "Created the bucket, '" << bucketName << "', in the region, '" << clientConfig.region << "'." << std::endl; } } // 2. Upload a local file to the bucket. Aws::String key = "key-for-test"; { Aws::S3::Model::PutObjectRequest request; request.SetBucket(bucketName); request.SetKey(key); std::shared_ptr<Aws::FStream> input_data = Aws::MakeShared<Aws::FStream>("SampleAllocationTag", uploadFilePath, std::ios_base::in | std::ios_base::binary); if (!input_data->is_open()) { std::cerr << "Error: unable to open file, '" << uploadFilePath << "'." << std::endl; AwsDoc::S3::deleteBucket(bucketName, client); return false; } request.SetBody(input_data); Aws::S3::Model::PutObjectOutcome outcome = client.PutObject(request); if (!outcome.IsSuccess()) { std::cerr << "Error: putObject: " << outcome.GetError().GetMessage() << std::endl; AwsDoc::S3::deleteObjectFromBucket(bucketName, key, client); AwsDoc::S3::deleteBucket(bucketName, client); return false; } else { std::cout << "Added the object with the key, '" << key << "', to the bucket, '" << bucketName << "'." << std::endl; } } // 3. Download the object to a local file. { Aws::S3::Model::GetObjectRequest request; request.SetBucket(bucketName); request.SetKey(key); Aws::S3::Model::GetObjectOutcome outcome = client.GetObject(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &err = outcome.GetError(); std::cerr << "Error: getObject: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { std::cout << "Downloaded the object with the key, '" << key << "', in the bucket, '" << bucketName << "'." << std::endl; Aws::IOStream &ioStream = outcome.GetResultWithOwnership(). GetBody(); Aws::OFStream outStream(saveFilePath, std::ios_base::out | std::ios_base::binary); if (!outStream.is_open()) { std::cout << "Error: unable to open file, '" << saveFilePath << "'." << std::endl; } else { outStream << ioStream.rdbuf(); std::cout << "Wrote the downloaded object to the file '" << saveFilePath << "'." << std::endl; } } } // 4. Copy the object to a different "folder" in the bucket. Aws::String copiedToKey = "test-folder/" + key; { Aws::S3::Model::CopyObjectRequest request; request.WithBucket(bucketName) .WithKey(copiedToKey) .WithCopySource(bucketName + "/" + key); Aws::S3::Model::CopyObjectOutcome outcome = client.CopyObject(request); if (!outcome.IsSuccess()) { std::cerr << "Error: copyObject: " << outcome.GetError().GetMessage() << std::endl; } else { std::cout << "Copied the object with the key, '" << key << "', to the key, '" << copiedToKey << ", in the bucket, '" << bucketName << "'." << std::endl; } } // 5. List objects in the bucket. { Aws::S3::Model::ListObjectsV2Request request; request.WithBucket(bucketName); Aws::String continuationToken; Aws::Vector<Aws::S3::Model::Object> allObjects; do { if (!continuationToken.empty()) { request.SetContinuationToken(continuationToken); } Aws::S3::Model::ListObjectsV2Outcome outcome = client.ListObjectsV2( request); if (!outcome.IsSuccess()) { std::cerr << "Error: ListObjects: " << outcome.GetError().GetMessage() << std::endl; break; } else { Aws::Vector<Aws::S3::Model::Object> objects = outcome.GetResult().GetContents(); allObjects.insert(allObjects.end(), objects.begin(), objects.end()); continuationToken = outcome.GetResult().GetContinuationToken(); } } while (!continuationToken.empty()); std::cout << allObjects.size() << " objects in the bucket, '" << bucketName << "':" << std::endl; for (Aws::S3::Model::Object &object: allObjects) { std::cout << " '" << object.GetKey() << "'" << std::endl; } } // 6. Delete all objects in the bucket. // All objects in the bucket must be deleted before deleting the bucket. AwsDoc::S3::deleteObjectFromBucket(bucketName, copiedToKey, client); AwsDoc::S3::deleteObjectFromBucket(bucketName, key, client); // 7. Delete the bucket. return AwsDoc::S3::deleteBucket(bucketName, client); } bool AwsDoc::S3::deleteObjectFromBucket(const Aws::String &bucketName, const Aws::String &key, Aws::S3::S3Client &client) { Aws::S3::Model::DeleteObjectRequest request; request.SetBucket(bucketName); request.SetKey(key); Aws::S3::Model::DeleteObjectOutcome outcome = client.DeleteObject(request); if (!outcome.IsSuccess()) { std::cerr << "Error: deleteObject: " << outcome.GetError().GetMessage() << std::endl; } else { std::cout << "Deleted the object with the key, '" << key << "', from the bucket, '" << bucketName << "'." << std::endl; } return outcome.IsSuccess(); } bool AwsDoc::S3::deleteBucket(const Aws::String &bucketName, Aws::S3::S3Client &client) { Aws::S3::Model::DeleteBucketRequest request; request.SetBucket(bucketName); Aws::S3::Model::DeleteBucketOutcome outcome = client.DeleteBucket(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &err = outcome.GetError(); std::cerr << "Error: deleteBucket: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { std::cout << "Deleted the bucket, '" << bucketName << "'." << std::endl; } return outcome.IsSuccess(); }

Actions

The following code example shows how to use AbortMultipartUpload.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

//! Abort a multipart upload to an S3 bucket. /*! \param bucket: The name of the S3 bucket where the object will be uploaded. \param key: The unique identifier (key) for the object within the S3 bucket. \param uploadID: An upload ID string. \param client: The S3 client instance used to perform the upload operation. \return bool: Function succeeded. */ bool AwsDoc::S3::abortMultipartUpload(const Aws::String &bucket, const Aws::String &key, const Aws::String &uploadID, const Aws::S3::S3Client &client) { Aws::S3::Model::AbortMultipartUploadRequest request; request.SetBucket(bucket); request.SetKey(key); request.SetUploadId(uploadID); Aws::S3::Model::AbortMultipartUploadOutcome outcome = client.AbortMultipartUpload(request); if (outcome.IsSuccess()) { std::cout << "Multipart upload aborted." << std::endl; } else { std::cerr << "Error aborting multipart upload: " << outcome.GetError().GetMessage() << std::endl; } return outcome.IsSuccess(); }

The following code example shows how to use CompleteMultipartUpload.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

//! Complete a multipart upload to an S3 bucket. /*! \param bucket: The name of the S3 bucket where the object will be uploaded. \param key: The unique identifier (key) for the object within the S3 bucket. \param uploadID: An upload ID string. \param parts: A vector of CompleteParts. \param client: The S3 client instance used to perform the upload operation. \return CompleteMultipartUploadOutcome: The request outcome. */ Aws::S3::Model::CompleteMultipartUploadOutcome AwsDoc::S3::completeMultipartUpload(const Aws::String &bucket, const Aws::String &key, const Aws::String &uploadID, const Aws::Vector<Aws::S3::Model::CompletedPart> &parts, const Aws::S3::S3Client &client) { Aws::S3::Model::CompletedMultipartUpload completedMultipartUpload; completedMultipartUpload.SetParts(parts); Aws::S3::Model::CompleteMultipartUploadRequest request; request.SetBucket(bucket); request.SetKey(key); request.SetUploadId(uploadID); request.SetMultipartUpload(completedMultipartUpload); Aws::S3::Model::CompleteMultipartUploadOutcome outcome = client.CompleteMultipartUpload(request); if (!outcome.IsSuccess()) { std::cerr << "Error completing multipart upload: " << outcome.GetError().GetMessage() << std::endl; } return outcome; }

The following code example shows how to use CopyObject.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::copyObject(const Aws::String &objectKey, const Aws::String &fromBucket, const Aws::String &toBucket, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); Aws::S3::Model::CopyObjectRequest request; request.WithCopySource(fromBucket + "/" + objectKey) .WithKey(objectKey) .WithBucket(toBucket); Aws::S3::Model::CopyObjectOutcome outcome = client.CopyObject(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &err = outcome.GetError(); std::cerr << "Error: copyObject: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { std::cout << "Successfully copied " << objectKey << " from " << fromBucket << " to " << toBucket << "." << std::endl; } return outcome.IsSuccess(); }
  • For API details, see CopyObject in AWS SDK for C++ API Reference.

The following code example shows how to use CreateBucket.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::createBucket(const Aws::String &bucketName, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); Aws::S3::Model::CreateBucketRequest request; request.SetBucket(bucketName); if (clientConfig.region != "us-east-1") { Aws::S3::Model::CreateBucketConfiguration createBucketConfig; createBucketConfig.SetLocationConstraint( Aws::S3::Model::BucketLocationConstraintMapper::GetBucketLocationConstraintForName( clientConfig.region)); request.SetCreateBucketConfiguration(createBucketConfig); } Aws::S3::Model::CreateBucketOutcome outcome = client.CreateBucket(request); if (!outcome.IsSuccess()) { auto err = outcome.GetError(); std::cerr << "Error: createBucket: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { std::cout << "Created bucket " << bucketName << " in the specified AWS Region." << std::endl; } return outcome.IsSuccess(); }
  • For API details, see CreateBucket in AWS SDK for C++ API Reference.

The following code example shows how to use CreateMultipartUpload.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

//! Create a multipart upload. /*! \param bucket: The name of the S3 bucket where the object will be uploaded. \param key: The unique identifier (key) for the object within the S3 bucket. \param client: The S3 client instance used to perform the upload operation. \return Aws::String: Upload ID or empty string if failed. */ Aws::String AwsDoc::S3::createMultipartUpload(const Aws::String &bucket, const Aws::String &key, Aws::S3::Model::ChecksumAlgorithm checksumAlgorithm, const Aws::S3::S3Client &client) { Aws::S3::Model::CreateMultipartUploadRequest request; request.SetBucket(bucket); request.SetKey(key); if (checksumAlgorithm != Aws::S3::Model::ChecksumAlgorithm::NOT_SET) { request.SetChecksumAlgorithm(checksumAlgorithm); } Aws::S3::Model::CreateMultipartUploadOutcome outcome = client.CreateMultipartUpload(request); Aws::String uploadID; if (outcome.IsSuccess()) { uploadID = outcome.GetResult().GetUploadId(); } else { std::cerr << "Error creating multipart upload: " << outcome.GetError().GetMessage() << std::endl; } return uploadID; }

The following code example shows how to use DeleteBucket.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::deleteBucket(const Aws::String &bucketName, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); Aws::S3::Model::DeleteBucketRequest request; request.SetBucket(bucketName); Aws::S3::Model::DeleteBucketOutcome outcome = client.DeleteBucket(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &err = outcome.GetError(); std::cerr << "Error: deleteBucket: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { std::cout << "The bucket was deleted" << std::endl; } return outcome.IsSuccess(); }
  • For API details, see DeleteBucket in AWS SDK for C++ API Reference.

The following code example shows how to use DeleteBucketPolicy.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::deleteBucketPolicy(const Aws::String &bucketName, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); Aws::S3::Model::DeleteBucketPolicyRequest request; request.SetBucket(bucketName); Aws::S3::Model::DeleteBucketPolicyOutcome outcome = client.DeleteBucketPolicy(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &err = outcome.GetError(); std::cerr << "Error: deleteBucketPolicy: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { std::cout << "Policy was deleted from the bucket." << std::endl; } return outcome.IsSuccess(); }

The following code example shows how to use DeleteBucketWebsite.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::deleteBucketWebsite(const Aws::String &bucketName, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); Aws::S3::Model::DeleteBucketWebsiteRequest request; request.SetBucket(bucketName); Aws::S3::Model::DeleteBucketWebsiteOutcome outcome = client.DeleteBucketWebsite(request); if (!outcome.IsSuccess()) { auto err = outcome.GetError(); std::cerr << "Error: deleteBucketWebsite: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { std::cout << "Website configuration was removed." << std::endl; } return outcome.IsSuccess(); }

The following code example shows how to use DeleteObject.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::deleteObject(const Aws::String &objectKey, const Aws::String &fromBucket, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); Aws::S3::Model::DeleteObjectRequest request; request.WithKey(objectKey) .WithBucket(fromBucket); Aws::S3::Model::DeleteObjectOutcome outcome = client.DeleteObject(request); if (!outcome.IsSuccess()) { auto err = outcome.GetError(); std::cerr << "Error: deleteObject: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { std::cout << "Successfully deleted the object." << std::endl; } return outcome.IsSuccess(); }
  • For API details, see DeleteObject in AWS SDK for C++ API Reference.

The following code example shows how to use DeleteObjects.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::deleteObjects(const std::vector<Aws::String> &objectKeys, const Aws::String &fromBucket, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); Aws::S3::Model::DeleteObjectsRequest request; Aws::S3::Model::Delete deleteObject; for (const Aws::String &objectKey: objectKeys) { deleteObject.AddObjects(Aws::S3::Model::ObjectIdentifier().WithKey(objectKey)); } request.SetDelete(deleteObject); request.SetBucket(fromBucket); Aws::S3::Model::DeleteObjectsOutcome outcome = client.DeleteObjects(request); if (!outcome.IsSuccess()) { auto err = outcome.GetError(); std::cerr << "Error deleting objects. " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { std::cout << "Successfully deleted the objects."; for (size_t i = 0; i < objectKeys.size(); ++i) { std::cout << objectKeys[i]; if (i < objectKeys.size() - 1) { std::cout << ", "; } } std::cout << " from bucket " << fromBucket << "." << std::endl; } return outcome.IsSuccess(); }
  • For API details, see DeleteObjects in AWS SDK for C++ API Reference.

The following code example shows how to use GetBucketAcl.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::getBucketAcl(const Aws::String &bucketName, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client s3Client(clientConfig); Aws::S3::Model::GetBucketAclRequest request; request.SetBucket(bucketName); Aws::S3::Model::GetBucketAclOutcome outcome = s3Client.GetBucketAcl(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &err = outcome.GetError(); std::cerr << "Error: getBucketAcl: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { Aws::Vector<Aws::S3::Model::Grant> grants = outcome.GetResult().GetGrants(); for (auto it = grants.begin(); it != grants.end(); it++) { Aws::S3::Model::Grant grant = *it; Aws::S3::Model::Grantee grantee = grant.GetGrantee(); std::cout << "For bucket " << bucketName << ": " << std::endl << std::endl; if (grantee.TypeHasBeenSet()) { std::cout << "Type: " << getGranteeTypeString(grantee.GetType()) << std::endl; } if (grantee.DisplayNameHasBeenSet()) { std::cout << "Display name: " << grantee.GetDisplayName() << std::endl; } if (grantee.EmailAddressHasBeenSet()) { std::cout << "Email address: " << grantee.GetEmailAddress() << std::endl; } if (grantee.IDHasBeenSet()) { std::cout << "ID: " << grantee.GetID() << std::endl; } if (grantee.URIHasBeenSet()) { std::cout << "URI: " << grantee.GetURI() << std::endl; } std::cout << "Permission: " << getPermissionString(grant.GetPermission()) << std::endl << std::endl; } } return outcome.IsSuccess(); } //! Routine which converts a built-in type enumeration to a human-readable string. /*! \param type: Type enumeration. \return String: Human-readable string. */ Aws::String getGranteeTypeString(const Aws::S3::Model::Type &type) { switch (type) { case Aws::S3::Model::Type::AmazonCustomerByEmail: return "Email address of an AWS account"; case Aws::S3::Model::Type::CanonicalUser: return "Canonical user ID of an AWS account"; case Aws::S3::Model::Type::Group: return "Predefined Amazon S3 group"; case Aws::S3::Model::Type::NOT_SET: return "Not set"; default: return "Type unknown"; } } //! Routine which converts a built-in type enumeration to a human-readable string. /*! \param permission: Permission enumeration. \return String: Human-readable string. */ Aws::String getPermissionString(const Aws::S3::Model::Permission &permission) { switch (permission) { case Aws::S3::Model::Permission::FULL_CONTROL: return "Can list objects in this bucket, create/overwrite/delete " "objects in this bucket, and read/write this " "bucket's permissions"; case Aws::S3::Model::Permission::NOT_SET: return "Permission not set"; case Aws::S3::Model::Permission::READ: return "Can list objects in this bucket"; case Aws::S3::Model::Permission::READ_ACP: return "Can read this bucket's permissions"; case Aws::S3::Model::Permission::WRITE: return "Can create, overwrite, and delete objects in this bucket"; case Aws::S3::Model::Permission::WRITE_ACP: return "Can write this bucket's permissions"; default: return "Permission unknown"; } return "Permission unknown"; }
  • For API details, see GetBucketAcl in AWS SDK for C++ API Reference.

The following code example shows how to use GetBucketPolicy.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::getBucketPolicy(const Aws::String &bucketName, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client s3Client(clientConfig); Aws::S3::Model::GetBucketPolicyRequest request; request.SetBucket(bucketName); Aws::S3::Model::GetBucketPolicyOutcome outcome = s3Client.GetBucketPolicy(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &err = outcome.GetError(); std::cerr << "Error: getBucketPolicy: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { Aws::StringStream policy_stream; Aws::String line; outcome.GetResult().GetPolicy() >> line; policy_stream << line; std::cout << "Retrieve the policy for bucket '" << bucketName << "':\n\n" << policy_stream.str() << std::endl; } return outcome.IsSuccess(); }

The following code example shows how to use GetBucketWebsite.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::getWebsiteConfig(const Aws::String &bucketName, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client s3Client(clientConfig); Aws::S3::Model::GetBucketWebsiteRequest request; request.SetBucket(bucketName); Aws::S3::Model::GetBucketWebsiteOutcome outcome = s3Client.GetBucketWebsite(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &err = outcome.GetError(); std::cerr << "Error: GetBucketWebsite: " << err.GetMessage() << std::endl; } else { Aws::S3::Model::GetBucketWebsiteResult websiteResult = outcome.GetResult(); std::cout << "Success: GetBucketWebsite: " << std::endl << std::endl << "For bucket '" << bucketName << "':" << std::endl << "Index page : " << websiteResult.GetIndexDocument().GetSuffix() << std::endl << "Error page: " << websiteResult.GetErrorDocument().GetKey() << std::endl; } return outcome.IsSuccess(); }

The following code example shows how to use GetObject.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::getObject(const Aws::String &objectKey, const Aws::String &fromBucket, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); Aws::S3::Model::GetObjectRequest request; request.SetBucket(fromBucket); request.SetKey(objectKey); Aws::S3::Model::GetObjectOutcome outcome = client.GetObject(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &err = outcome.GetError(); std::cerr << "Error: getObject: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { std::cout << "Successfully retrieved '" << objectKey << "' from '" << fromBucket << "'." << std::endl; } return outcome.IsSuccess(); }
  • For API details, see GetObject in AWS SDK for C++ API Reference.

The following code example shows how to use GetObjectAcl.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::getObjectAcl(const Aws::String &bucketName, const Aws::String &objectKey, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client s3Client(clientConfig); Aws::S3::Model::GetObjectAclRequest request; request.SetBucket(bucketName); request.SetKey(objectKey); Aws::S3::Model::GetObjectAclOutcome outcome = s3Client.GetObjectAcl(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &err = outcome.GetError(); std::cerr << "Error: getObjectAcl: " << err.GetExceptionName() << ": " << err.GetMessage() << std::endl; } else { Aws::Vector<Aws::S3::Model::Grant> grants = outcome.GetResult().GetGrants(); for (auto it = grants.begin(); it != grants.end(); it++) { std::cout << "For object " << objectKey << ": " << std::endl << std::endl; Aws::S3::Model::Grant grant = *it; Aws::S3::Model::Grantee grantee = grant.GetGrantee(); if (grantee.TypeHasBeenSet()) { std::cout << "Type: " << getGranteeTypeString(grantee.GetType()) << std::endl; } if (grantee.DisplayNameHasBeenSet()) { std::cout << "Display name: " << grantee.GetDisplayName() << std::endl; } if (grantee.EmailAddressHasBeenSet()) { std::cout << "Email address: " << grantee.GetEmailAddress() << std::endl; } if (grantee.IDHasBeenSet()) { std::cout << "ID: " << grantee.GetID() << std::endl; } if (grantee.URIHasBeenSet()) { std::cout << "URI: " << grantee.GetURI() << std::endl; } std::cout << "Permission: " << getPermissionString(grant.GetPermission()) << std::endl << std::endl; } } return outcome.IsSuccess(); } //! Routine which converts a built-in type enumeration to a human-readable string. /*! \param type: Type enumeration. \return String: Human-readable string */ Aws::String getGranteeTypeString(const Aws::S3::Model::Type &type) { switch (type) { case Aws::S3::Model::Type::AmazonCustomerByEmail: return "Email address of an AWS account"; case Aws::S3::Model::Type::CanonicalUser: return "Canonical user ID of an AWS account"; case Aws::S3::Model::Type::Group: return "Predefined Amazon S3 group"; case Aws::S3::Model::Type::NOT_SET: return "Not set"; default: return "Type unknown"; } } //! Routine which converts a built-in type enumeration to a human-readable string. /*! \param permission: Permission enumeration. \return String: Human-readable string */ Aws::String getPermissionString(const Aws::S3::Model::Permission &permission) { switch (permission) { case Aws::S3::Model::Permission::FULL_CONTROL: return "Can read this object's data and its metadata, " "and read/write this object's permissions"; case Aws::S3::Model::Permission::NOT_SET: return "Permission not set"; case Aws::S3::Model::Permission::READ: return "Can read this object's data and its metadata"; case Aws::S3::Model::Permission::READ_ACP: return "Can read this object's permissions"; // case Aws::S3::Model::Permission::WRITE // Not applicable. case Aws::S3::Model::Permission::WRITE_ACP: return "Can write this object's permissions"; default: return "Permission unknown"; } }
  • For API details, see GetObjectAcl in AWS SDK for C++ API Reference.

The following code example shows how to use GetObjectAttributes.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

// ! Routine which retrieves the hash value of an object stored in an S3 bucket. /*! \param bucket: The name of the S3 bucket where the object is stored. \param key: The unique identifier (key) of the object within the S3 bucket. \param hashMethod: The hashing algorithm used to calculate the hash value of the object. \param[out] hashData: The retrieved hash. \param[out] partHashes: The part hashes if available. \param client: The S3 client instance used to retrieve the object. \return bool: Function succeeded. */ bool AwsDoc::S3::retrieveObjectHash(const Aws::String &bucket, const Aws::String &key, AwsDoc::S3::HASH_METHOD hashMethod, Aws::String &hashData, std::vector<Aws::String> *partHashes, const Aws::S3::S3Client &client) { Aws::S3::Model::GetObjectAttributesRequest request; request.SetBucket(bucket); request.SetKey(key); if (hashMethod == MD5) { Aws::Vector<Aws::S3::Model::ObjectAttributes> attributes; attributes.push_back(Aws::S3::Model::ObjectAttributes::ETag); request.SetObjectAttributes(attributes); Aws::S3::Model::GetObjectAttributesOutcome outcome = client.GetObjectAttributes( request); if (outcome.IsSuccess()) { const Aws::S3::Model::GetObjectAttributesResult &result = outcome.GetResult(); hashData = result.GetETag(); } else { std::cerr << "Error retrieving object etag attributes." << outcome.GetError().GetMessage() << std::endl; return false; } } else { // hashMethod != MD5 Aws::Vector<Aws::S3::Model::ObjectAttributes> attributes; attributes.push_back(Aws::S3::Model::ObjectAttributes::Checksum); request.SetObjectAttributes(attributes); Aws::S3::Model::GetObjectAttributesOutcome outcome = client.GetObjectAttributes( request); if (outcome.IsSuccess()) { const Aws::S3::Model::GetObjectAttributesResult &result = outcome.GetResult(); switch (hashMethod) { case AwsDoc::S3::DEFAULT: // NOLINT(*-branch-clone) break; // Default is not supported. #pragma clang diagnostic push #pragma ide diagnostic ignored "UnreachableCode" case AwsDoc::S3::MD5: break; // MD5 is not supported. #pragma clang diagnostic pop case AwsDoc::S3::SHA1: hashData = result.GetChecksum().GetChecksumSHA1(); break; case AwsDoc::S3::SHA256: hashData = result.GetChecksum().GetChecksumSHA256(); break; case AwsDoc::S3::CRC32: hashData = result.GetChecksum().GetChecksumCRC32(); break; case AwsDoc::S3::CRC32C: hashData = result.GetChecksum().GetChecksumCRC32C(); break; default: std::cerr << "Unknown hash method." << std::endl; return false; } } else { std::cerr << "Error retrieving object checksum attributes." << outcome.GetError().GetMessage() << std::endl; return false; } if (nullptr != partHashes) { attributes.clear(); attributes.push_back(Aws::S3::Model::ObjectAttributes::ObjectParts); request.SetObjectAttributes(attributes); outcome = client.GetObjectAttributes(request); if (outcome.IsSuccess()) { const Aws::S3::Model::GetObjectAttributesResult &result = outcome.GetResult(); const Aws::Vector<Aws::S3::Model::ObjectPart> parts = result.GetObjectParts().GetParts(); for (const Aws::S3::Model::ObjectPart &part: parts) { switch (hashMethod) { case AwsDoc::S3::DEFAULT: // Default is not supported. NOLINT(*-branch-clone) break; case AwsDoc::S3::MD5: // MD5 is not supported. break; case AwsDoc::S3::SHA1: partHashes->push_back(part.GetChecksumSHA1()); break; case AwsDoc::S3::SHA256: partHashes->push_back(part.GetChecksumSHA256()); break; case AwsDoc::S3::CRC32: partHashes->push_back(part.GetChecksumCRC32()); break; case AwsDoc::S3::CRC32C: partHashes->push_back(part.GetChecksumCRC32C()); break; default: std::cerr << "Unknown hash method." << std::endl; return false; } } } else { std::cerr << "Error retrieving object attributes for object parts." << outcome.GetError().GetMessage() << std::endl; return false; } } } return true; }

The following code example shows how to use ListBuckets.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::listBuckets(const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); auto outcome = client.ListBuckets(); bool result = true; if (!outcome.IsSuccess()) { std::cerr << "Failed with error: " << outcome.GetError() << std::endl; result = false; } else { std::cout << "Found " << outcome.GetResult().GetBuckets().size() << " buckets\n"; for (auto &&b: outcome.GetResult().GetBuckets()) { std::cout << b.GetName() << std::endl; } } return result; }
  • For API details, see ListBuckets in AWS SDK for C++ API Reference.

The following code example shows how to use ListObjectsV2.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::listObjects(const Aws::String &bucketName, Aws::Vector<Aws::String> &keysResult, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client s3Client(clientConfig); Aws::S3::Model::ListObjectsV2Request request; request.WithBucket(bucketName); Aws::String continuationToken; // Used for pagination. Aws::Vector<Aws::S3::Model::Object> allObjects; do { if (!continuationToken.empty()) { request.SetContinuationToken(continuationToken); } auto outcome = s3Client.ListObjectsV2(request); if (!outcome.IsSuccess()) { std::cerr << "Error: listObjects: " << outcome.GetError().GetMessage() << std::endl; return false; } else { Aws::Vector<Aws::S3::Model::Object> objects = outcome.GetResult().GetContents(); allObjects.insert(allObjects.end(), objects.begin(), objects.end()); continuationToken = outcome.GetResult().GetNextContinuationToken(); } } while (!continuationToken.empty()); std::cout << allObjects.size() << " object(s) found:" << std::endl; for (const auto &object: allObjects) { std::cout << " " << object.GetKey() << std::endl; keysResult.push_back(object.GetKey()); } return true; }
  • For API details, see ListObjectsV2 in AWS SDK for C++ API Reference.

The following code example shows how to use PutBucketAcl.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::putBucketAcl(const Aws::String &bucketName, const Aws::String &ownerID, const Aws::String &granteePermission, const Aws::String &granteeType, const Aws::String &granteeID, const Aws::String &granteeEmailAddress, const Aws::String &granteeURI, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client s3Client(clientConfig); Aws::S3::Model::Owner owner; owner.SetID(ownerID); Aws::S3::Model::Grantee grantee; grantee.SetType(setGranteeType(granteeType)); if (!granteeEmailAddress.empty()) { grantee.SetEmailAddress(granteeEmailAddress); } if (!granteeID.empty()) { grantee.SetID(granteeID); } if (!granteeURI.empty()) { grantee.SetURI(granteeURI); } Aws::S3::Model::Grant grant; grant.SetGrantee(grantee); grant.SetPermission(setGranteePermission(granteePermission)); Aws::Vector<Aws::S3::Model::Grant> grants; grants.push_back(grant); Aws::S3::Model::AccessControlPolicy acp; acp.SetOwner(owner); acp.SetGrants(grants); Aws::S3::Model::PutBucketAclRequest request; request.SetAccessControlPolicy(acp); request.SetBucket(bucketName); Aws::S3::Model::PutBucketAclOutcome outcome = s3Client.PutBucketAcl(request); if (!outcome.IsSuccess()) { const Aws::S3::S3Error &error = outcome.GetError(); std::cerr << "Error: putBucketAcl: " << error.GetExceptionName() << " - " << error.GetMessage() << std::endl; } else { std::cout << "Successfully added an ACL to the bucket '" << bucketName << "'." << std::endl; } return outcome.IsSuccess(); } //! Routine which converts a human-readable string to a built-in type enumeration. /*! \param access: Human readable string. \return Permission: A Permission enum. */ Aws::S3::Model::Permission setGranteePermission(const Aws::String &access) { if (access == "FULL_CONTROL") return Aws::S3::Model::Permission::FULL_CONTROL; if (access == "WRITE") return Aws::S3::Model::Permission::WRITE; if (access == "READ") return Aws::S3::Model::Permission::READ; if (access == "WRITE_ACP") return Aws::S3::Model::Permission::WRITE_ACP; if (access == "READ_ACP") return Aws::S3::Model::Permission::READ_ACP; return Aws::S3::Model::Permission::NOT_SET; } //! Routine which converts a human-readable string to a built-in type enumeration. /*! \param type: Human readable string. \return Type: Type enumeration */ Aws::S3::Model::Type setGranteeType(const Aws::String &type) { if (type == "Amazon customer by email") return Aws::S3::Model::Type::AmazonCustomerByEmail; if (type == "Canonical user") return Aws::S3::Model::Type::CanonicalUser; if (type == "Group") return Aws::S3::Model::Type::Group; return Aws::S3::Model::Type::NOT_SET; }
  • For API details, see PutBucketAcl in AWS SDK for C++ API Reference.

The following code example shows how to use PutBucketPolicy.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::putBucketPolicy(const Aws::String &bucketName, const Aws::String &policyBody, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client s3Client(clientConfig); std::shared_ptr<Aws::StringStream> request_body = Aws::MakeShared<Aws::StringStream>(""); *request_body << policyBody; Aws::S3::Model::PutBucketPolicyRequest request; request.SetBucket(bucketName); request.SetBody(request_body); Aws::S3::Model::PutBucketPolicyOutcome outcome = s3Client.PutBucketPolicy(request); if (!outcome.IsSuccess()) { std::cerr << "Error: putBucketPolicy: " << outcome.GetError().GetMessage() << std::endl; } else { std::cout << "Set the following policy body for the bucket '" << bucketName << "':" << std::endl << std::endl; std::cout << policyBody << std::endl; } return outcome.IsSuccess(); } //! Build a policy JSON string. /*! \param userArn: Aws user Amazon Resource Name (ARN). For more information, see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-arns. \param bucketName: Name of a bucket. \return String: Policy as JSON string. */ Aws::String getPolicyString(const Aws::String &userArn, const Aws::String &bucketName) { return "{\n" " \"Version\":\"2012-10-17\",\n" " \"Statement\":[\n" " {\n" " \"Sid\": \"1\",\n" " \"Effect\": \"Allow\",\n" " \"Principal\": {\n" " \"AWS\": \"" + userArn + "\"\n"" },\n" " \"Action\": [ \"s3:getObject\" ],\n" " \"Resource\": [ \"arn:aws:s3:::" + bucketName + "/*\" ]\n" " }\n" " ]\n" "}"; }

The following code example shows how to use PutBucketWebsite.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::putWebsiteConfig(const Aws::String &bucketName, const Aws::String &indexPage, const Aws::String &errorPage, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); Aws::S3::Model::IndexDocument indexDocument; indexDocument.SetSuffix(indexPage); Aws::S3::Model::ErrorDocument errorDocument; errorDocument.SetKey(errorPage); Aws::S3::Model::WebsiteConfiguration websiteConfiguration; websiteConfiguration.SetIndexDocument(indexDocument); websiteConfiguration.SetErrorDocument(errorDocument); Aws::S3::Model::PutBucketWebsiteRequest request; request.SetBucket(bucketName); request.SetWebsiteConfiguration(websiteConfiguration); Aws::S3::Model::PutBucketWebsiteOutcome outcome = client.PutBucketWebsite(request); if (!outcome.IsSuccess()) { std::cerr << "Error: PutBucketWebsite: " << outcome.GetError().GetMessage() << std::endl; } else { std::cout << "Success: Set website configuration for bucket '" << bucketName << "'." << std::endl; } return outcome.IsSuccess(); }

The following code example shows how to use PutObject.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::putObject(const Aws::String &bucketName, const Aws::String &fileName, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client s3Client(clientConfig); Aws::S3::Model::PutObjectRequest request; request.SetBucket(bucketName); //We are using the name of the file as the key for the object in the bucket. //However, this is just a string and can be set according to your retrieval needs. request.SetKey(fileName); std::shared_ptr<Aws::IOStream> inputData = Aws::MakeShared<Aws::FStream>("SampleAllocationTag", fileName.c_str(), std::ios_base::in | std::ios_base::binary); if (!*inputData) { std::cerr << "Error unable to read file " << fileName << std::endl; return false; } request.SetBody(inputData); Aws::S3::Model::PutObjectOutcome outcome = s3Client.PutObject(request); if (!outcome.IsSuccess()) { std::cerr << "Error: putObject: " << outcome.GetError().GetMessage() << std::endl; } else { std::cout << "Added object '" << fileName << "' to bucket '" << bucketName << "'."; } return outcome.IsSuccess(); }
  • For API details, see PutObject in AWS SDK for C++ API Reference.

The following code example shows how to use PutObjectAcl.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

bool AwsDoc::S3::putObjectAcl(const Aws::String &bucketName, const Aws::String &objectKey, const Aws::String &ownerID, const Aws::String &granteePermission, const Aws::String &granteeType, const Aws::String &granteeID, const Aws::String &granteeEmailAddress, const Aws::String &granteeURI, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client s3Client(clientConfig); Aws::S3::Model::Owner owner; owner.SetID(ownerID); Aws::S3::Model::Grantee grantee; grantee.SetType(setGranteeType(granteeType)); if (!granteeEmailAddress.empty()) { grantee.SetEmailAddress(granteeEmailAddress); } if (!granteeID.empty()) { grantee.SetID(granteeID); } if (!granteeURI.empty()) { grantee.SetURI(granteeURI); } Aws::S3::Model::Grant grant; grant.SetGrantee(grantee); grant.SetPermission(setGranteePermission(granteePermission)); Aws::Vector<Aws::S3::Model::Grant> grants; grants.push_back(grant); Aws::S3::Model::AccessControlPolicy acp; acp.SetOwner(owner); acp.SetGrants(grants); Aws::S3::Model::PutObjectAclRequest request; request.SetAccessControlPolicy(acp); request.SetBucket(bucketName); request.SetKey(objectKey); Aws::S3::Model::PutObjectAclOutcome outcome = s3Client.PutObjectAcl(request); if (!outcome.IsSuccess()) { auto error = outcome.GetError(); std::cerr << "Error: putObjectAcl: " << error.GetExceptionName() << " - " << error.GetMessage() << std::endl; } else { std::cout << "Successfully added an ACL to the object '" << objectKey << "' in the bucket '" << bucketName << "'." << std::endl; } return outcome.IsSuccess(); } //! Routine which converts a human-readable string to a built-in type enumeration. /*! \param access: Human readable string. \return Permission: Permission enumeration. */ Aws::S3::Model::Permission setGranteePermission(const Aws::String &access) { if (access == "FULL_CONTROL") return Aws::S3::Model::Permission::FULL_CONTROL; if (access == "WRITE") return Aws::S3::Model::Permission::WRITE; if (access == "READ") return Aws::S3::Model::Permission::READ; if (access == "WRITE_ACP") return Aws::S3::Model::Permission::WRITE_ACP; if (access == "READ_ACP") return Aws::S3::Model::Permission::READ_ACP; return Aws::S3::Model::Permission::NOT_SET; } //! Routine which converts a human-readable string to a built-in type enumeration. /*! \param type: Human readable string. \return Type: Type enumeration. */ Aws::S3::Model::Type setGranteeType(const Aws::String &type) { if (type == "Amazon customer by email") return Aws::S3::Model::Type::AmazonCustomerByEmail; if (type == "Canonical user") return Aws::S3::Model::Type::CanonicalUser; if (type == "Group") return Aws::S3::Model::Type::Group; return Aws::S3::Model::Type::NOT_SET; }
  • For API details, see PutObjectAcl in AWS SDK for C++ API Reference.

The following code example shows how to use UploadPart.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

//! Upload a part to an S3 bucket. /*! \param bucket: The name of the S3 bucket where the object will be uploaded. \param key: The unique identifier (key) for the object within the S3 bucket. \param uploadID: An upload ID string. \param partNumber: \param checksumAlgorithm: Checksum algorithm, ignored when NOT_SET. \param calculatedHash: A data integrity hash to set, depending on the checksum algorithm, ignored when it is an empty string. \param body: An shared_ptr IOStream of the data to be uploaded. \param client: The S3 client instance used to perform the upload operation. \return UploadPartOutcome: The outcome. */ Aws::S3::Model::UploadPartOutcome AwsDoc::S3::uploadPart(const Aws::String &bucket, const Aws::String &key, const Aws::String &uploadID, int partNumber, Aws::S3::Model::ChecksumAlgorithm checksumAlgorithm, const Aws::String &calculatedHash, const std::shared_ptr<Aws::IOStream> &body, const Aws::S3::S3Client &client) { Aws::S3::Model::UploadPartRequest request; request.SetBucket(bucket); request.SetKey(key); request.SetUploadId(uploadID); request.SetPartNumber(partNumber); if (checksumAlgorithm != Aws::S3::Model::ChecksumAlgorithm::NOT_SET) { request.SetChecksumAlgorithm(checksumAlgorithm); } request.SetBody(body); if (!calculatedHash.empty()) { switch (checksumAlgorithm) { case Aws::S3::Model::ChecksumAlgorithm::NOT_SET: request.SetContentMD5(calculatedHash); break; case Aws::S3::Model::ChecksumAlgorithm::CRC32: request.SetChecksumCRC32(calculatedHash); break; case Aws::S3::Model::ChecksumAlgorithm::CRC32C: request.SetChecksumCRC32C(calculatedHash); break; case Aws::S3::Model::ChecksumAlgorithm::SHA1: request.SetChecksumSHA1(calculatedHash); break; case Aws::S3::Model::ChecksumAlgorithm::SHA256: request.SetChecksumSHA256(calculatedHash); break; } } return client.UploadPart(request); }
  • For API details, see UploadPart in AWS SDK for C++ API Reference.

Scenarios

The following code example shows how to create a presigned URL for Amazon S3 and upload an object.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

Generate a pre-signed URL to download an object.

//! Routine which demonstrates creating a pre-signed URL to download an object from an //! Amazon Simple Storage Service (Amazon S3) bucket. /*! \param bucketName: Name of the bucket. \param key: Name of an object key. \param expirationSeconds: Expiration in seconds for pre-signed URL. \param clientConfig: Aws client configuration. \return Aws::String: A pre-signed URL. */ Aws::String AwsDoc::S3::generatePreSignedGetObjectUrl(const Aws::String &bucketName, const Aws::String &key, uint64_t expirationSeconds, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); return client.GeneratePresignedUrl(bucketName, key, Aws::Http::HttpMethod::HTTP_GET, expirationSeconds); }

Download using libcurl.

static size_t myCurlWriteBack(char *buffer, size_t size, size_t nitems, void *userdata) { Aws::StringStream *str = (Aws::StringStream *) userdata; if (nitems > 0) { str->write(buffer, size * nitems); } return size * nitems; } //! Utility routine to test getObject with a pre-signed URL. /*! \param presignedURL: A pre-signed URL to get an object from a bucket. \param resultString: A string to hold the result. \return bool: Function succeeded. */ bool AwsDoc::S3::getObjectWithPresignedObjectUrl(const Aws::String &presignedURL, Aws::String &resultString) { CURL *curl = curl_easy_init(); CURLcode result; std::stringstream outWriteString; result = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outWriteString); if (result != CURLE_OK) { std::cerr << "Failed to set CURLOPT_WRITEDATA " << std::endl; return false; } result = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, myCurlWriteBack); if (result != CURLE_OK) { std::cerr << "Failed to set CURLOPT_WRITEFUNCTION" << std::endl; return false; } result = curl_easy_setopt(curl, CURLOPT_URL, presignedURL.c_str()); if (result != CURLE_OK) { std::cerr << "Failed to set CURLOPT_URL" << std::endl; return false; } result = curl_easy_perform(curl); if (result != CURLE_OK) { std::cerr << "Failed to perform CURL request" << std::endl; return false; } resultString = outWriteString.str(); if (resultString.find("<?xml") == 0) { std::cerr << "Failed to get object, response:\n" << resultString << std::endl; return false; } return true; }

Generate a pre-signed URL to upload an object.

//! Routine which demonstrates creating a pre-signed URL to upload an object to an //! Amazon Simple Storage Service (Amazon S3) bucket. /*! \param bucketName: Name of the bucket. \param key: Name of an object key. \param clientConfig: Aws client configuration. \return Aws::String: A pre-signed URL. */ Aws::String AwsDoc::S3::generatePreSignedPutObjectUrl(const Aws::String &bucketName, const Aws::String &key, uint64_t expirationSeconds, const Aws::S3::S3ClientConfiguration &clientConfig) { Aws::S3::S3Client client(clientConfig); return client.GeneratePresignedUrl(bucketName, key, Aws::Http::HttpMethod::HTTP_PUT, expirationSeconds); }

Upload using libcurl.

static size_t myCurlReadBack(char *buffer, size_t size, size_t nitems, void *userdata) { Aws::StringStream *str = (Aws::StringStream *) userdata; str->read(buffer, size * nitems); return str->gcount(); } static size_t myCurlWriteBack(char *buffer, size_t size, size_t nitems, void *userdata) { Aws::StringStream *str = (Aws::StringStream *) userdata; if (nitems > 0) { str->write(buffer, size * nitems); } return size * nitems; } //! Utility routine to test putObject with a pre-signed URL. /*! \param presignedURL: A pre-signed URL to put an object in a bucket. \param data: Body of the putObject request. \return bool: Function succeeded. */ bool AwsDoc::S3::PutStringWithPresignedObjectURL(const Aws::String &presignedURL, const Aws::String &data) { CURL *curl = curl_easy_init(); CURLcode result; Aws::StringStream readStringStream; readStringStream << data; result = curl_easy_setopt(curl, CURLOPT_READFUNCTION, myCurlReadBack); if (result != CURLE_OK) { std::cerr << "Failed to set CURLOPT_READFUNCTION" << std::endl; return false; } result = curl_easy_setopt(curl, CURLOPT_READDATA, &readStringStream); if (result != CURLE_OK) { std::cerr << "Failed to set CURLOPT_READDATA" << std::endl; return false; } result = curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) data.size()); if (result != CURLE_OK) { std::cerr << "Failed to set CURLOPT_INFILESIZE_LARGE" << std::endl; return false; } result = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, myCurlWriteBack); if (result != CURLE_OK) { std::cerr << "Failed to set CURLOPT_WRITEFUNCTION" << std::endl; return false; } std::stringstream outWriteString; result = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outWriteString); if (result != CURLE_OK) { std::cerr << "Failed to set CURLOPT_WRITEDATA " << std::endl; return false; } result = curl_easy_setopt(curl, CURLOPT_URL, presignedURL.c_str()); if (result != CURLE_OK) { std::cerr << "Failed to set CURLOPT_URL" << std::endl; return false; } result = curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); if (result != CURLE_OK) { std::cerr << "Failed to set CURLOPT_PUT" << std::endl; return false; } result = curl_easy_perform(curl); if (result != CURLE_OK) { std::cerr << "Failed to perform CURL request" << std::endl; return false; } std::string outString = outWriteString.str(); if (outString.empty()) { std::cout << "Successfully put object." << std::endl; return true; } else { std::cout << "A server error was encountered, output:\n" << outString << std::endl; return false; } }

The following code example shows how to create a serverless application that lets users manage photos using labels.

SDK for C++

Shows how to develop a photo asset management application that detects labels in images using Amazon Rekognition and stores them for later retrieval.

For complete source code and instructions on how to set up and run, see the full example on GitHub.

For a deep dive into the origin of this example see the post on AWS Community.

Services used in this example
  • API Gateway

  • DynamoDB

  • Lambda

  • Amazon Rekognition

  • Amazon S3

  • Amazon SNS

The following code example shows how to work with S3 object integrity features.

SDK for C++
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

Run an interactive scenario demonstrating Amazon S3 object integrity features.

//! Routine which runs the S3 object integrity workflow. /*! \param clientConfig: Aws client configuration. \return bool: Function succeeded. */ bool AwsDoc::S3::s3ObjectIntegrityWorkflow( const Aws::S3::S3ClientConfiguration &clientConfiguration) { /* * Create a large file to be used for multipart uploads. */ if (!createLargeFileIfNotExists()) { std::cerr << "Workflow exiting because large file creation failed." << std::endl; return false; } Aws::String bucketName = TEST_BUCKET_PREFIX; bucketName += Aws::Utils::UUID::RandomUUID(); bucketName = Aws::Utils::StringUtils::ToLower(bucketName.c_str()); bucketName.resize(std::min(bucketName.size(), MAX_BUCKET_NAME_LENGTH)); introductoryExplanations(bucketName); if (!AwsDoc::S3::createBucket(bucketName, clientConfiguration)) { std::cerr << "Workflow exiting because bucket creation failed." << std::endl; return false; } Aws::S3::S3ClientConfiguration s3ClientConfiguration(clientConfiguration); std::shared_ptr<Aws::S3::S3Client> client = Aws::MakeShared<Aws::S3::S3Client>("S3Client", s3ClientConfiguration); printAsterisksLine(); std::cout << "Choose from one of the following checksum algorithms." << std::endl; for (HASH_METHOD hashMethod = DEFAULT; hashMethod <= SHA256; ++hashMethod) { std::cout << " " << hashMethod << " - " << stringForHashMethod(hashMethod) << std::endl; } HASH_METHOD chosenHashMethod = askQuestionForIntRange("Enter an index: ", DEFAULT, SHA256); gUseCalculatedChecksum = !askYesNoQuestion( "Let the SDK calculate the checksum for you? (y/n) "); printAsterisksLine(); std::cout << "The workflow will now upload a file using PutObject." << std::endl; std::cout << "Object integrity will be verified using the " << stringForHashMethod(chosenHashMethod) << " algorithm." << std::endl; if (gUseCalculatedChecksum) { std::cout << "A checksum computed by this workflow will be used for object integrity verification," << std::endl; std::cout << "except for the TransferManager upload." << std::endl; } else { std::cout << "A checksum computed by the SDK will be used for object integrity verification." << std::endl; } pressEnterToContinue(); printAsterisksLine(); std::shared_ptr<Aws::IOStream> inputData = Aws::MakeShared<Aws::FStream>("SampleAllocationTag", TEST_FILE, std::ios_base::in | std::ios_base::binary); if (!*inputData) { std::cerr << "Error unable to read file " << TEST_FILE << std::endl; cleanUp(bucketName, clientConfiguration); return false; } Hasher hasher; HASH_METHOD putObjectHashMethod = chosenHashMethod; if (putObjectHashMethod == DEFAULT) { putObjectHashMethod = MD5; // MD5 is the default hash method for PutObject. std::cout << "The default checksum algorithm for PutObject is " << stringForHashMethod(putObjectHashMethod) << std::endl; } // Demonstrate in code how the hash is computed. if (!hasher.calculateObjectHash(*inputData, putObjectHashMethod)) { std::cerr << "Error calculating hash for file " << TEST_FILE << std::endl; cleanUp(bucketName, clientConfiguration); return false; } Aws::String key = stringForHashMethod(putObjectHashMethod); key += "_"; key += TEST_FILE_KEY; Aws::String localHash = hasher.getBase64HashString(); // Upload the object with PutObject if (!putObjectWithHash(bucketName, key, localHash, putObjectHashMethod, inputData, chosenHashMethod == DEFAULT, *client)) { std::cerr << "Error putting file " << TEST_FILE << " to bucket " << bucketName << " with key " << key << std::endl; cleanUp(bucketName, clientConfiguration); return false; } Aws::String retrievedHash; if (!retrieveObjectHash(bucketName, key, putObjectHashMethod, retrievedHash, nullptr, *client)) { std::cerr << "Error getting file " << TEST_FILE << " from bucket " << bucketName << " with key " << key << std::endl; cleanUp(bucketName, clientConfiguration); return false; } explainPutObjectResults(); verifyHashingResults(retrievedHash, hasher, "PutObject upload", putObjectHashMethod); printAsterisksLine(); pressEnterToContinue(); key = "tr_"; key += stringForHashMethod(chosenHashMethod) + "_" + MULTI_PART_TEST_FILE; introductoryTransferManagerUploadExplanations(key); HASH_METHOD transferManagerHashMethod = chosenHashMethod; if (transferManagerHashMethod == DEFAULT) { transferManagerHashMethod = CRC32; // The default hash method for the TransferManager is CRC32. std::cout << "The default checksum algorithm for TransferManager is " << stringForHashMethod(transferManagerHashMethod) << std::endl; } // Upload the large file using the transfer manager. if (!doTransferManagerUpload(bucketName, key, transferManagerHashMethod, chosenHashMethod == DEFAULT, client)) { std::cerr << "Exiting because of an error in doTransferManagerUpload." << std::endl; cleanUp(bucketName, clientConfiguration); return false; } std::vector<Aws::String> retrievedTransferManagerPartHashes; Aws::String retrievedTransferManagerFinalHash; // Retrieve all the hashes for the TransferManager upload. if (!retrieveObjectHash(bucketName, key, transferManagerHashMethod, retrievedTransferManagerFinalHash, &retrievedTransferManagerPartHashes, *client)) { std::cerr << "Exiting because of an error in retrieveObjectHash for TransferManager." << std::endl; cleanUp(bucketName, clientConfiguration); return false; } AwsDoc::S3::Hasher locallyCalculatedFinalHash; std::vector<Aws::String> locallyCalculatedPartHashes; // Calculate the hashes locally to demonstrate how TransferManager hashes are computed. if (!calculatePartHashesForFile(transferManagerHashMethod, MULTI_PART_TEST_FILE, UPLOAD_BUFFER_SIZE, locallyCalculatedFinalHash, locallyCalculatedPartHashes)) { std::cerr << "Exiting because of an error in calculatePartHashesForFile." << std::endl; cleanUp(bucketName, clientConfiguration); return false; } verifyHashingResults(retrievedTransferManagerFinalHash, locallyCalculatedFinalHash, "TransferManager upload", transferManagerHashMethod, retrievedTransferManagerPartHashes, locallyCalculatedPartHashes); printAsterisksLine(); key = "mp_"; key += stringForHashMethod(chosenHashMethod) + "_" + MULTI_PART_TEST_FILE; multiPartUploadExplanations(key, chosenHashMethod); pressEnterToContinue(); std::shared_ptr<Aws::IOStream> largeFileInputData = Aws::MakeShared<Aws::FStream>("SampleAllocationTag", MULTI_PART_TEST_FILE, std::ios_base::in | std::ios_base::binary); if (!largeFileInputData->good()) { std::cerr << "Error unable to read file " << TEST_FILE << std::endl; cleanUp(bucketName, clientConfiguration); return false; } HASH_METHOD multipartUploadHashMethod = chosenHashMethod; if (multipartUploadHashMethod == DEFAULT) { multipartUploadHashMethod = MD5; // The default hash method for multipart uploads is MD5. std::cout << "The default checksum algorithm for multipart upload is " << stringForHashMethod(putObjectHashMethod) << std::endl; } AwsDoc::S3::Hasher hashData; std::vector<Aws::String> partHashes; if (!doMultipartUpload(bucketName, key, multipartUploadHashMethod, largeFileInputData, chosenHashMethod == DEFAULT, hashData, partHashes, *client)) { std::cerr << "Exiting because of an error in doMultipartUpload." << std::endl; cleanUp(bucketName, clientConfiguration); return false; } std::cout << "Finished multipart upload of with hash method " << stringForHashMethod(multipartUploadHashMethod) << std::endl; std::cout << "Now we will retrieve the checksums from the server." << std::endl; retrievedHash.clear(); std::vector<Aws::String> retrievedPartHashes; if (!retrieveObjectHash(bucketName, key, multipartUploadHashMethod, retrievedHash, &retrievedPartHashes, *client)) { std::cerr << "Exiting because of an error in retrieveObjectHash for multipart." << std::endl; cleanUp(bucketName, clientConfiguration); return false; } verifyHashingResults(retrievedHash, hashData, "MultiPart upload", multipartUploadHashMethod, retrievedPartHashes, partHashes); printAsterisksLine(); if (askYesNoQuestion("Would you like to delete the resources created in this workflow? (y/n)")) { return cleanUp(bucketName, clientConfiguration); } else { std::cout << "The bucket " << bucketName << " was not deleted." << std::endl; return true; } } //! Routine which uploads an object to an S3 bucket with different object integrity hashing methods. /*! \param bucket: The name of the S3 bucket where the object will be uploaded. \param key: The unique identifier (key) for the object within the S3 bucket. \param hashData: The hash value that will be associated with the uploaded object. \param hashMethod: The hashing algorithm to use when calculating the hash value. \param body: The data content of the object being uploaded. \param useDefaultHashMethod: A flag indicating whether to use the default hash method or the one specified in the hashMethod parameter. \param client: The S3 client instance used to perform the upload operation. \return bool: Function succeeded. */ bool AwsDoc::S3::putObjectWithHash(const Aws::String &bucket, const Aws::String &key, const Aws::String &hashData, AwsDoc::S3::HASH_METHOD hashMethod, const std::shared_ptr<Aws::IOStream> &body, bool useDefaultHashMethod, const Aws::S3::S3Client &client) { Aws::S3::Model::PutObjectRequest request; request.SetBucket(bucket); request.SetKey(key); if (!useDefaultHashMethod) { if (hashMethod != MD5) { request.SetChecksumAlgorithm(getChecksumAlgorithmForHashMethod(hashMethod)); } } if (gUseCalculatedChecksum) { switch (hashMethod) { case AwsDoc::S3::MD5: request.SetContentMD5(hashData); break; case AwsDoc::S3::SHA1: request.SetChecksumSHA1(hashData); break; case AwsDoc::S3::SHA256: request.SetChecksumSHA256(hashData); break; case AwsDoc::S3::CRC32: request.SetChecksumCRC32(hashData); break; case AwsDoc::S3::CRC32C: request.SetChecksumCRC32C(hashData); break; default: std::cerr << "Unknown hash method." << std::endl; return false; } } request.SetBody(body); Aws::S3::Model::PutObjectOutcome outcome = client.PutObject(request); body->seekg(0, body->beg); if (outcome.IsSuccess()) { std::cout << "Object successfully uploaded." << std::endl; } else { std::cerr << "Error uploading object." << outcome.GetError().GetMessage() << std::endl; } return outcome.IsSuccess(); } // ! Routine which retrieves the hash value of an object stored in an S3 bucket. /*! \param bucket: The name of the S3 bucket where the object is stored. \param key: The unique identifier (key) of the object within the S3 bucket. \param hashMethod: The hashing algorithm used to calculate the hash value of the object. \param[out] hashData: The retrieved hash. \param[out] partHashes: The part hashes if available. \param client: The S3 client instance used to retrieve the object. \return bool: Function succeeded. */ bool AwsDoc::S3::retrieveObjectHash(const Aws::String &bucket, const Aws::String &key, AwsDoc::S3::HASH_METHOD hashMethod, Aws::String &hashData, std::vector<Aws::String> *partHashes, const Aws::S3::S3Client &client) { Aws::S3::Model::GetObjectAttributesRequest request; request.SetBucket(bucket); request.SetKey(key); if (hashMethod == MD5) { Aws::Vector<Aws::S3::Model::ObjectAttributes> attributes; attributes.push_back(Aws::S3::Model::ObjectAttributes::ETag); request.SetObjectAttributes(attributes); Aws::S3::Model::GetObjectAttributesOutcome outcome = client.GetObjectAttributes( request); if (outcome.IsSuccess()) { const Aws::S3::Model::GetObjectAttributesResult &result = outcome.GetResult(); hashData = result.GetETag(); } else { std::cerr << "Error retrieving object etag attributes." << outcome.GetError().GetMessage() << std::endl; return false; } } else { // hashMethod != MD5 Aws::Vector<Aws::S3::Model::ObjectAttributes> attributes; attributes.push_back(Aws::S3::Model::ObjectAttributes::Checksum); request.SetObjectAttributes(attributes); Aws::S3::Model::GetObjectAttributesOutcome outcome = client.GetObjectAttributes( request); if (outcome.IsSuccess()) { const Aws::S3::Model::GetObjectAttributesResult &result = outcome.GetResult(); switch (hashMethod) { case AwsDoc::S3::DEFAULT: // NOLINT(*-branch-clone) break; // Default is not supported. #pragma clang diagnostic push #pragma ide diagnostic ignored "UnreachableCode" case AwsDoc::S3::MD5: break; // MD5 is not supported. #pragma clang diagnostic pop case AwsDoc::S3::SHA1: hashData = result.GetChecksum().GetChecksumSHA1(); break; case AwsDoc::S3::SHA256: hashData = result.GetChecksum().GetChecksumSHA256(); break; case AwsDoc::S3::CRC32: hashData = result.GetChecksum().GetChecksumCRC32(); break; case AwsDoc::S3::CRC32C: hashData = result.GetChecksum().GetChecksumCRC32C(); break; default: std::cerr << "Unknown hash method." << std::endl; return false; } } else { std::cerr << "Error retrieving object checksum attributes." << outcome.GetError().GetMessage() << std::endl; return false; } if (nullptr != partHashes) { attributes.clear(); attributes.push_back(Aws::S3::Model::ObjectAttributes::ObjectParts); request.SetObjectAttributes(attributes); outcome = client.GetObjectAttributes(request); if (outcome.IsSuccess()) { const Aws::S3::Model::GetObjectAttributesResult &result = outcome.GetResult(); const Aws::Vector<Aws::S3::Model::ObjectPart> parts = result.GetObjectParts().GetParts(); for (const Aws::S3::Model::ObjectPart &part: parts) { switch (hashMethod) { case AwsDoc::S3::DEFAULT: // Default is not supported. NOLINT(*-branch-clone) break; case AwsDoc::S3::MD5: // MD5 is not supported. break; case AwsDoc::S3::SHA1: partHashes->push_back(part.GetChecksumSHA1()); break; case AwsDoc::S3::SHA256: partHashes->push_back(part.GetChecksumSHA256()); break; case AwsDoc::S3::CRC32: partHashes->push_back(part.GetChecksumCRC32()); break; case AwsDoc::S3::CRC32C: partHashes->push_back(part.GetChecksumCRC32C()); break; default: std::cerr << "Unknown hash method." << std::endl; return false; } } } else { std::cerr << "Error retrieving object attributes for object parts." << outcome.GetError().GetMessage() << std::endl; return false; } } } return true; } //! Verifies the hashing results between the retrieved and local hashes. /*! \param retrievedHash The hash value retrieved from the remote source. \param localHash The hash value calculated locally. \param uploadtype The type of upload (e.g., "multipart", "single-part"). \param hashMethod The hashing method used (e.g., MD5, SHA-256). \param retrievedPartHashes (Optional) The list of hashes for the individual parts retrieved from the remote source. \param localPartHashes (Optional) The list of hashes for the individual parts calculated locally. */ void AwsDoc::S3::verifyHashingResults(const Aws::String &retrievedHash, const Hasher &localHash, const Aws::String &uploadtype, HASH_METHOD hashMethod, const std::vector<Aws::String> &retrievedPartHashes, const std::vector<Aws::String> &localPartHashes) { std::cout << "For " << uploadtype << " retrieved hash is " << retrievedHash << std::endl; if (!retrievedPartHashes.empty()) { std::cout << retrievedPartHashes.size() << " part hash(es) were also retrieved." << std::endl; for (auto &retrievedPartHash: retrievedPartHashes) { std::cout << " Part hash " << retrievedPartHash << std::endl; } } Aws::String hashString; if (hashMethod == MD5) { hashString = localHash.getHexHashString(); if (!localPartHashes.empty()) { hashString += "-" + std::to_string(localPartHashes.size()); } } else { hashString = localHash.getBase64HashString(); } bool allMatch = true; if (hashString != retrievedHash) { std::cerr << "For " << uploadtype << ", the main hashes do not match" << std::endl; std::cerr << "Local hash- '" << hashString << "'" << std::endl; std::cerr << "Remote hash - '" << retrievedHash << "'" << std::endl; allMatch = false; } if (hashMethod != MD5) { if (localPartHashes.size() != retrievedPartHashes.size()) { std::cerr << "For " << uploadtype << ", the number of part hashes do not match" << std::endl; std::cerr << "Local number of hashes- '" << localPartHashes.size() << "'" << std::endl; std::cerr << "Remote number of hashes - '" << retrievedPartHashes.size() << "'" << std::endl; } for (int i = 0; i < localPartHashes.size(); ++i) { if (localPartHashes[i] != retrievedPartHashes[i]) { std::cerr << "For " << uploadtype << ", the part hashes do not match for part " << i + 1 << "." << std::endl; std::cerr << "Local hash- '" << localPartHashes[i] << "'" << std::endl; std::cerr << "Remote hash - '" << retrievedPartHashes[i] << "'" << std::endl; allMatch = false; } } } if (allMatch) { std::cout << "For " << uploadtype << ", locally and remotely calculated hashes all match!" << std::endl; } } static void transferManagerErrorCallback(const Aws::Transfer::TransferManager *, const std::shared_ptr<const Aws::Transfer::TransferHandle> &, const Aws::Client::AWSError<Aws::S3::S3Errors> &err) { std::cerr << "Error during transfer: '" << err.GetMessage() << "'" << std::endl; } static void transferManagerStatusCallback(const Aws::Transfer::TransferManager *, const std::shared_ptr<const Aws::Transfer::TransferHandle> &handle) { if (handle->GetStatus() == Aws::Transfer::TransferStatus::IN_PROGRESS) { std::cout << "Bytes transferred: " << handle->GetBytesTransferred() << std::endl; } } //! Routine which uploads an object to an S3 bucket using the AWS C++ SDK's Transfer Manager. /*! \param bucket: The name of the S3 bucket where the object will be uploaded. \param key: The unique identifier (key) for the object within the S3 bucket. \param hashMethod: The hashing algorithm to use when calculating the hash value. \param useDefaultHashMethod: A flag indicating whether to use the default hash method or the one specified in the hashMethod parameter. \param client: The S3 client instance used to perform the upload operation. \return bool: Function succeeded. */ bool AwsDoc::S3::doTransferManagerUpload(const Aws::String &bucket, const Aws::String &key, AwsDoc::S3::HASH_METHOD hashMethod, bool useDefaultHashMethod, const std::shared_ptr<Aws::S3::S3Client> &client) { std::shared_ptr<Aws::Utils::Threading::PooledThreadExecutor> executor = Aws::MakeShared<Aws::Utils::Threading::PooledThreadExecutor>( "executor", 25); Aws::Transfer::TransferManagerConfiguration transfer_config(executor.get()); transfer_config.s3Client = client; transfer_config.bufferSize = UPLOAD_BUFFER_SIZE; if (!useDefaultHashMethod) { if (hashMethod == MD5) { transfer_config.computeContentMD5 = true; } else { transfer_config.checksumAlgorithm = getChecksumAlgorithmForHashMethod( hashMethod); } } transfer_config.errorCallback = transferManagerErrorCallback; transfer_config.transferStatusUpdatedCallback = transferManagerStatusCallback; std::shared_ptr<Aws::Transfer::TransferManager> transfer_manager = Aws::Transfer::TransferManager::Create( transfer_config); std::cout << "Uploading the file..." << std::endl; std::shared_ptr<Aws::Transfer::TransferHandle> uploadHandle = transfer_manager->UploadFile(MULTI_PART_TEST_FILE, bucket, key, "text/plain", Aws::Map<Aws::String, Aws::String>()); uploadHandle->WaitUntilFinished(); bool success = uploadHandle->GetStatus() == Aws::Transfer::TransferStatus::COMPLETED; if (!success) { Aws::Client::AWSError<Aws::S3::S3Errors> err = uploadHandle->GetLastError(); std::cerr << "File upload failed: " << err.GetMessage() << std::endl; } return success; } //! Routine which calculates the hash values for each part of a file being uploaded to an S3 bucket. /*! \param hashMethod: The hashing algorithm to use when calculating the hash values. \param fileName: The path to the file for which the part hashes will be calculated. \param bufferSize: The size of the buffer to use when reading the file. \param[out] hashDataResult: The Hasher object that will store the concatenated hash value. \param[out] partHashes: The vector that will store the calculated hash values for each part of the file. \return bool: Function succeeded. */ bool AwsDoc::S3::calculatePartHashesForFile(AwsDoc::S3::HASH_METHOD hashMethod, const Aws::String &fileName, size_t bufferSize, AwsDoc::S3::Hasher &hashDataResult, std::vector<Aws::String> &partHashes) { std::ifstream fileStream(fileName.c_str(), std::ifstream::binary); fileStream.seekg(0, std::ifstream::end); size_t objectSize = fileStream.tellg(); fileStream.seekg(0, std::ifstream::beg); std::vector<unsigned char> totalHashBuffer; size_t uploadedBytes = 0; while (uploadedBytes < objectSize) { std::vector<unsigned char> buffer(bufferSize); std::streamsize bytesToRead = static_cast<std::streamsize>(std::min(buffer.size(), objectSize - uploadedBytes)); fileStream.read((char *) buffer.data(), bytesToRead); Aws::Utils::Stream::PreallocatedStreamBuf preallocatedStreamBuf(buffer.data(), bytesToRead); std::shared_ptr<Aws::IOStream> body = Aws::MakeShared<Aws::IOStream>("SampleAllocationTag", &preallocatedStreamBuf); Hasher hasher; if (!hasher.calculateObjectHash(*body, hashMethod)) { std::cerr << "Error calculating hash." << std::endl; return false; } Aws::String base64HashString = hasher.getBase64HashString(); partHashes.push_back(base64HashString); Aws::Utils::ByteBuffer hashBuffer = hasher.getByteBufferHash(); totalHashBuffer.insert(totalHashBuffer.end(), hashBuffer.GetUnderlyingData(), hashBuffer.GetUnderlyingData() + hashBuffer.GetLength()); uploadedBytes += bytesToRead; } return hashDataResult.calculateObjectHash(totalHashBuffer, hashMethod); } //! Create a multipart upload. /*! \param bucket: The name of the S3 bucket where the object will be uploaded. \param key: The unique identifier (key) for the object within the S3 bucket. \param client: The S3 client instance used to perform the upload operation. \return Aws::String: Upload ID or empty string if failed. */ Aws::String AwsDoc::S3::createMultipartUpload(const Aws::String &bucket, const Aws::String &key, Aws::S3::Model::ChecksumAlgorithm checksumAlgorithm, const Aws::S3::S3Client &client) { Aws::S3::Model::CreateMultipartUploadRequest request; request.SetBucket(bucket); request.SetKey(key); if (checksumAlgorithm != Aws::S3::Model::ChecksumAlgorithm::NOT_SET) { request.SetChecksumAlgorithm(checksumAlgorithm); } Aws::S3::Model::CreateMultipartUploadOutcome outcome = client.CreateMultipartUpload(request); Aws::String uploadID; if (outcome.IsSuccess()) { uploadID = outcome.GetResult().GetUploadId(); } else { std::cerr << "Error creating multipart upload: " << outcome.GetError().GetMessage() << std::endl; } return uploadID; } //! Upload a part to an S3 bucket. /*! \param bucket: The name of the S3 bucket where the object will be uploaded. \param key: The unique identifier (key) for the object within the S3 bucket. \param uploadID: An upload ID string. \param partNumber: \param checksumAlgorithm: Checksum algorithm, ignored when NOT_SET. \param calculatedHash: A data integrity hash to set, depending on the checksum algorithm, ignored when it is an empty string. \param body: An shared_ptr IOStream of the data to be uploaded. \param client: The S3 client instance used to perform the upload operation. \return UploadPartOutcome: The outcome. */ Aws::S3::Model::UploadPartOutcome AwsDoc::S3::uploadPart(const Aws::String &bucket, const Aws::String &key, const Aws::String &uploadID, int partNumber, Aws::S3::Model::ChecksumAlgorithm checksumAlgorithm, const Aws::String &calculatedHash, const std::shared_ptr<Aws::IOStream> &body, const Aws::S3::S3Client &client) { Aws::S3::Model::UploadPartRequest request; request.SetBucket(bucket); request.SetKey(key); request.SetUploadId(uploadID); request.SetPartNumber(partNumber); if (checksumAlgorithm != Aws::S3::Model::ChecksumAlgorithm::NOT_SET) { request.SetChecksumAlgorithm(checksumAlgorithm); } request.SetBody(body); if (!calculatedHash.empty()) { switch (checksumAlgorithm) { case Aws::S3::Model::ChecksumAlgorithm::NOT_SET: request.SetContentMD5(calculatedHash); break; case Aws::S3::Model::ChecksumAlgorithm::CRC32: request.SetChecksumCRC32(calculatedHash); break; case Aws::S3::Model::ChecksumAlgorithm::CRC32C: request.SetChecksumCRC32C(calculatedHash); break; case Aws::S3::Model::ChecksumAlgorithm::SHA1: request.SetChecksumSHA1(calculatedHash); break; case Aws::S3::Model::ChecksumAlgorithm::SHA256: request.SetChecksumSHA256(calculatedHash); break; } } return client.UploadPart(request); } //! Abort a multipart upload to an S3 bucket. /*! \param bucket: The name of the S3 bucket where the object will be uploaded. \param key: The unique identifier (key) for the object within the S3 bucket. \param uploadID: An upload ID string. \param client: The S3 client instance used to perform the upload operation. \return bool: Function succeeded. */ bool AwsDoc::S3::abortMultipartUpload(const Aws::String &bucket, const Aws::String &key, const Aws::String &uploadID, const Aws::S3::S3Client &client) { Aws::S3::Model::AbortMultipartUploadRequest request; request.SetBucket(bucket); request.SetKey(key); request.SetUploadId(uploadID); Aws::S3::Model::AbortMultipartUploadOutcome outcome = client.AbortMultipartUpload(request); if (outcome.IsSuccess()) { std::cout << "Multipart upload aborted." << std::endl; } else { std::cerr << "Error aborting multipart upload: " << outcome.GetError().GetMessage() << std::endl; } return outcome.IsSuccess(); } //! Complete a multipart upload to an S3 bucket. /*! \param bucket: The name of the S3 bucket where the object will be uploaded. \param key: The unique identifier (key) for the object within the S3 bucket. \param uploadID: An upload ID string. \param parts: A vector of CompleteParts. \param client: The S3 client instance used to perform the upload operation. \return CompleteMultipartUploadOutcome: The request outcome. */ Aws::S3::Model::CompleteMultipartUploadOutcome AwsDoc::S3::completeMultipartUpload(const Aws::String &bucket, const Aws::String &key, const Aws::String &uploadID, const Aws::Vector<Aws::S3::Model::CompletedPart> &parts, const Aws::S3::S3Client &client) { Aws::S3::Model::CompletedMultipartUpload completedMultipartUpload; completedMultipartUpload.SetParts(parts); Aws::S3::Model::CompleteMultipartUploadRequest request; request.SetBucket(bucket); request.SetKey(key); request.SetUploadId(uploadID); request.SetMultipartUpload(completedMultipartUpload); Aws::S3::Model::CompleteMultipartUploadOutcome outcome = client.CompleteMultipartUpload(request); if (!outcome.IsSuccess()) { std::cerr << "Error completing multipart upload: " << outcome.GetError().GetMessage() << std::endl; } return outcome; } //! Routine which performs a multi-part upload. /*! \param bucket: The name of the S3 bucket where the object will be uploaded. \param key: The unique identifier (key) for the object within the S3 bucket. \param hashMethod: The hashing algorithm to use when calculating the hash value. \param ioStream: An IOStream for the data to be uploaded. \param useDefaultHashMethod: A flag indicating whether to use the default hash method or the one specified in the hashMethod parameter. \param[out] hashDataResult: The Hasher object that will store the concatenated hash value. \param[out] partHashes: The vector that will store the calculated hash values for each part of the file. \param client: The S3 client instance used to perform the upload operation. \return bool: Function succeeded. */ bool AwsDoc::S3::doMultipartUpload(const Aws::String &bucket, const Aws::String &key, AwsDoc::S3::HASH_METHOD hashMethod, const std::shared_ptr<Aws::IOStream> &ioStream, bool useDefaultHashMethod, AwsDoc::S3::Hasher &hashDataResult, std::vector<Aws::String> &partHashes, const Aws::S3::S3Client &client) { // Get object size. ioStream->seekg(0, ioStream->end); size_t objectSize = ioStream->tellg(); ioStream->seekg(0, ioStream->beg); Aws::S3::Model::ChecksumAlgorithm checksumAlgorithm = Aws::S3::Model::ChecksumAlgorithm::NOT_SET; if (!useDefaultHashMethod) { if (hashMethod != MD5) { checksumAlgorithm = getChecksumAlgorithmForHashMethod(hashMethod); } } Aws::String uploadID = createMultipartUpload(bucket, key, checksumAlgorithm, client); if (uploadID.empty()) { return false; } std::vector<unsigned char> totalHashBuffer; bool uploadSucceeded = true; std::streamsize uploadedBytes = 0; int partNumber = 1; Aws::Vector<Aws::S3::Model::CompletedPart> parts; while (uploadedBytes < objectSize) { std::cout << "Uploading part " << partNumber << "." << std::endl; std::vector<unsigned char> buffer(UPLOAD_BUFFER_SIZE); std::streamsize bytesToRead = static_cast<std::streamsize>(std::min(buffer.size(), objectSize - uploadedBytes)); ioStream->read((char *) buffer.data(), bytesToRead); Aws::Utils::Stream::PreallocatedStreamBuf preallocatedStreamBuf(buffer.data(), bytesToRead); std::shared_ptr<Aws::IOStream> body = Aws::MakeShared<Aws::IOStream>("SampleAllocationTag", &preallocatedStreamBuf); Hasher hasher; if (!hasher.calculateObjectHash(*body, hashMethod)) { std::cerr << "Error calculating hash." << std::endl; uploadSucceeded = false; break; } Aws::String base64HashString = hasher.getBase64HashString(); partHashes.push_back(base64HashString); Aws::Utils::ByteBuffer hashBuffer = hasher.getByteBufferHash(); totalHashBuffer.insert(totalHashBuffer.end(), hashBuffer.GetUnderlyingData(), hashBuffer.GetUnderlyingData() + hashBuffer.GetLength()); Aws::String calculatedHash; if (gUseCalculatedChecksum) { calculatedHash = base64HashString; } Aws::S3::Model::UploadPartOutcome uploadPartOutcome = uploadPart(bucket, key, uploadID, partNumber, checksumAlgorithm, base64HashString, body, client); if (uploadPartOutcome.IsSuccess()) { const Aws::S3::Model::UploadPartResult &uploadPartResult = uploadPartOutcome.GetResult(); Aws::S3::Model::CompletedPart completedPart; completedPart.SetETag(uploadPartResult.GetETag()); completedPart.SetPartNumber(partNumber); switch (hashMethod) { case AwsDoc::S3::MD5: break; // Do nothing. case AwsDoc::S3::SHA1: completedPart.SetChecksumSHA1(uploadPartResult.GetChecksumSHA1()); break; case AwsDoc::S3::SHA256: completedPart.SetChecksumSHA256(uploadPartResult.GetChecksumSHA256()); break; case AwsDoc::S3::CRC32: completedPart.SetChecksumCRC32(uploadPartResult.GetChecksumCRC32()); break; case AwsDoc::S3::CRC32C: completedPart.SetChecksumCRC32C(uploadPartResult.GetChecksumCRC32C()); break; default: std::cerr << "Unhandled hash method for completedPart." << std::endl; break; } parts.push_back(completedPart); } else { std::cerr << "Error uploading part. " << uploadPartOutcome.GetError().GetMessage() << std::endl; uploadSucceeded = false; break; } uploadedBytes += bytesToRead; partNumber++; } if (!uploadSucceeded) { abortMultipartUpload(bucket, key, uploadID, client); return false; } else { Aws::S3::Model::CompleteMultipartUploadOutcome completeMultipartUploadOutcome = completeMultipartUpload(bucket, key, uploadID, parts, client); if (completeMultipartUploadOutcome.IsSuccess()) { std::cout << "Multipart upload completed." << std::endl; if (!hashDataResult.calculateObjectHash(totalHashBuffer, hashMethod)) { std::cerr << "Error calculating hash." << std::endl; return false; } } else { std::cerr << "Error completing multipart upload." << completeMultipartUploadOutcome.GetError().GetMessage() << std::endl; } return completeMultipartUploadOutcome.IsSuccess(); } } //! Routine which retrieves the string for a HASH_METHOD constant. /*! \param: hashMethod: A HASH_METHOD constant. \return: String: A string description of the hash method. */ Aws::String AwsDoc::S3::stringForHashMethod(AwsDoc::S3::HASH_METHOD hashMethod) { switch (hashMethod) { case AwsDoc::S3::DEFAULT: return "Default"; case AwsDoc::S3::MD5: return "MD5"; case AwsDoc::S3::SHA1: return "SHA1"; case AwsDoc::S3::SHA256: return "SHA256"; case AwsDoc::S3::CRC32: return "CRC32"; case AwsDoc::S3::CRC32C: return "CRC32C"; default: return "Unknown"; } } //! Routine that returns the ChecksumAlgorithm for a HASH_METHOD constant. /*! \param: hashMethod: A HASH_METHOD constant. \return: ChecksumAlgorithm: The ChecksumAlgorithm enum. */ Aws::S3::Model::ChecksumAlgorithm AwsDoc::S3::getChecksumAlgorithmForHashMethod(AwsDoc::S3::HASH_METHOD hashMethod) { Aws::S3::Model::ChecksumAlgorithm result = Aws::S3::Model::ChecksumAlgorithm::NOT_SET; switch (hashMethod) { case AwsDoc::S3::DEFAULT: std::cerr << "getChecksumAlgorithmForHashMethod- DEFAULT is not valid." << std::endl; break; // Default is not supported. case AwsDoc::S3::MD5: break; // Ignore MD5. case AwsDoc::S3::SHA1: result = Aws::S3::Model::ChecksumAlgorithm::SHA1; break; case AwsDoc::S3::SHA256: result = Aws::S3::Model::ChecksumAlgorithm::SHA256; break; case AwsDoc::S3::CRC32: result = Aws::S3::Model::ChecksumAlgorithm::CRC32; break; case AwsDoc::S3::CRC32C: result = Aws::S3::Model::ChecksumAlgorithm::CRC32C; break; default: std::cerr << "Unknown hash method." << std::endl; break; } return result; } //! Routine which cleans up after the example is complete. /*! \param bucket: The name of the S3 bucket where the object was uploaded. \param clientConfiguration: The client configuration for the S3 client. \return bool: Function succeeded. */ bool AwsDoc::S3::cleanUp(const Aws::String &bucketName, const Aws::S3::S3ClientConfiguration &clientConfiguration) { Aws::Vector<Aws::String> keysResult; bool result = true; if (AwsDoc::S3::listObjects(bucketName, keysResult, clientConfiguration)) { if (!keysResult.empty()) { result = AwsDoc::S3::deleteObjects(keysResult, bucketName, clientConfiguration); } } else { result = false; } return result && AwsDoc::S3::deleteBucket(bucketName, clientConfiguration); } //! Console interaction introducing the workflow. /*! \param bucketName: The name of the S3 bucket to use. */ void AwsDoc::S3::introductoryExplanations(const Aws::String &bucketName) { std::cout << "Welcome to the Amazon Simple Storage Service (Amazon S3) object integrity workflow." << std::endl; printAsterisksLine(); std::cout << "This workflow demonstrates how Amazon S3 uses checksum values to verify the integrity of data\n"; std::cout << "uploaded to Amazon S3 buckets" << std::endl; std::cout << "The AWS SDK for C++ automatically handles checksums.\n"; std::cout << "By default it calculates a checksum that is uploaded with an object.\n" << "The default checksum algorithm for PutObject and MultiPart upload is an MD5 hash.\n" << "The default checksum algorithm for TransferManager uploads is a CRC32 checksum." << std::endl; std::cout << "You can override the default behavior, requiring one of the following checksums,\n"; std::cout << "MD5, CRC32, CRC32C, SHA-1 or SHA-256." << std::endl; std::cout << "You can also set the checksum hash value, instead of letting the SDK calculate the value." << std::endl; std::cout << "For more information, see https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html." << std::endl; std::cout << "This workflow will locally compute checksums for files uploaded to an Amazon S3 bucket,\n"; std::cout << "even when the SDK also computes the checksum." << std::endl; std::cout << "This is done to provide demonstration code for how the checksums are calculated." << std::endl; std::cout << "A bucket named '" << bucketName << "' will be created for the object uploads." << std::endl; } //! Console interaction which explains the PutObject results. /*! */ void AwsDoc::S3::explainPutObjectResults() { std::cout << "The upload was successful.\n"; std::cout << "If the checksums had not matched, the upload would have failed." << std::endl; std::cout << "The checksums calculated by the server have been retrieved using the GetObjectAttributes." << std::endl; std::cout << "The locally calculated checksums have been verified against the retrieved checksums." << std::endl; } //! Console interaction explaining transfer manager uploads. /*! \param objectKey: The key for the object being uploaded. */ void AwsDoc::S3::introductoryTransferManagerUploadExplanations( const Aws::String &objectKey) { std::cout << "Now the workflow will demonstrate object integrity for TransferManager multi-part uploads." << std::endl; std::cout << "The AWS C++ SDK has a TransferManager class which simplifies multipart uploads." << std::endl; std::cout << "The following code lets the TransferManager handle much of the checksum configuration." << std::endl; std::cout << "An object with the key '" << objectKey << " will be uploaded by the TransferManager using a " << BUFFER_SIZE_IN_MEGABYTES << " MB buffer." << std::endl; if (gUseCalculatedChecksum) { std::cout << "For TransferManager uploads, this demo always lets the SDK calculate the hash value." << std::endl; } pressEnterToContinue(); printAsterisksLine(); } //! Console interaction explaining multi-part uploads. /*! \param objectKey: The key for the object being uploaded. \param chosenHashMethod: The hash method selected by the user. */ void AwsDoc::S3::multiPartUploadExplanations(const Aws::String &objectKey, HASH_METHOD chosenHashMethod) { std::cout << "Now we will provide an in-depth demonstration of multi-part uploading by calling the multi-part upload APIs directly." << std::endl; std::cout << "These are the same APIs used by the TransferManager when uploading large files." << std::endl; std::cout << "In the following code, the checksums are also calculated locally and then compared." << std::endl; std::cout << "For multi-part uploads, a checksum is uploaded with each part. The final checksum is a concatenation of" << std::endl; std::cout << "the checksums for each part." << std::endl; std::cout << "This is explained in the user guide, https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html,\"" << " in the section \"Using part-level checksums for multipart uploads\"." << std::endl; std::cout << "Starting multipart upload of with hash method " << stringForHashMethod(chosenHashMethod) << " uploading to with object key\n" << "'" << objectKey << "'," << std::endl; } //! Create a large file for doing multi-part uploads. /*! */ bool AwsDoc::S3::createLargeFileIfNotExists() { // Generate a large file by writing this source file multiple times to a new file. if (std::filesystem::exists(MULTI_PART_TEST_FILE)) { return true; } std::ofstream newFile(MULTI_PART_TEST_FILE, std::ios::out | std::ios::binary); if (!newFile) { std::cerr << "createLargeFileIfNotExists- Error creating file " << MULTI_PART_TEST_FILE << std::endl; return false; } std::ifstream input(TEST_FILE, std::ios::in | std::ios::binary); if (!input) { std::cerr << "Error opening file " << TEST_FILE << std::endl; return false; } std::stringstream buffer; buffer << input.rdbuf(); input.close(); while (newFile.tellp() < LARGE_FILE_SIZE && !newFile.bad()) { buffer.seekg(std::stringstream::beg); newFile << buffer.rdbuf(); } newFile.close(); return true; }