Is the AWS S3 iOS SDK compatible with Spaces?

Has anyone successfully used AWS S3 iOS SDK to upload to Spaces? I’m using AWSS3 v2.6.10.

In my appDelegate/didFinishLaunchingWithOptions:

        let endpoint = AWSEndpoint(urlString: "")
        let credentialsProvider = AWSStaticCredentialsProvider(accessKey:"SPACES_API_ACCESS_KEY", secretKey: "SPACES_API_SECRET_KEY")
        let defaultServiceConfiguration = AWSServiceConfiguration(region: AWSRegionType.USEast1, endpoint: endpoint, credentialsProvider: credentialsProvider)

        defaultServiceConfiguration?.maxRetryCount = 5
        defaultServiceConfiguration?.timeoutIntervalForRequest = 30
        AWSServiceManager.default().defaultServiceConfiguration = defaultServiceConfiguration

My AWSS3TransferManagerUploadRequest:

        let fileManager = FileManager.default
        let path = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("\(newImage).jpeg")
        let imageData = UIImageJPEGRepresentation(newImage, 1.0)
        fileManager.createFile(atPath: path as String, contents: imageData, attributes: nil)
        let fileURL = URL(fileURLWithPath: path)
        guard let uploadRequest = AWSS3TransferManagerUploadRequest() else { return }
        uploadRequest.bucket = "MY_BUCKET"
        uploadRequest.key = "test_key"
        uploadRequest.body = fileURL

        let transferManager = AWSS3TransferManager.default()
        transferManager.upload(uploadRequest).continueOnSuccessWith { task -> Any? in
            if let error = task.error as NSError? {
                if error.domain == AWSS3TransferManagerErrorDomain, let code = AWSS3TransferManagerErrorType(rawValue: error.code) {
                    switch code {
                    case .cancelled, .paused:
                        print("Error uploading: \(String(describing: uploadRequest.key)) Error: \(error)")
                } else {
                    print("Error uploading: \(String(describing: uploadRequest.key)) Error: \(error)")
                return nil

            let uploadOutput = task.result
            print("Upload complete for: \(String(describing: uploadRequest.key))")
            print("uploadOutput: \(String(describing: uploadOutput))")
            return nil

The above configuration times out with the following Request:

user-agent:aws-sdk-iOS/2.6.10 iOS/11.2 en_US transfer-manager

2018-01-14 11:27:11:149 TapRoom[42942:4077877] payload 
2018-01-14 11:27:11:149 TapRoom[42942:4077877] AWS4 String to Sign: [AWS4-HMAC-SHA256

    Authorization = "AWS4-HMAC-SHA256 Credential=SPACES_API_ACCESS_KEY/20180114/us-east-1/s3/aws4_request, SignedHeaders=content-length;host;user-agent;x-amz-date, Signature=d16f6791edd66a6937c50fdc0c8e12bb5e9bc45b1c4b81df4f7413fdd049343e";
    "Content-Length" = 1357634;
    Host = "";
    "User-Agent" = "aws-sdk-iOS/2.6.10 iOS/11.2 en_US transfer-manager";
    "X-Amz-Date" = 20180114T162743Z;

And error message:

2018-01-14 11:27:43:490 TapRoom[42942:4078252] Session task failed with error: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x7b0c000aafa0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=, NSErrorFailingURLKey=, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.}

I’ve tried changing my endpoint from to and I get the following response:

<?xml version="1.0" encoding="UTF-8"?><Error><Code>SignatureDoesNotMatch</Code><RequestId>tx0000000000000000732e6-005a5b86c6-f7aef-nyc3a</RequestId><HostId>f7aef-nyc3a-nyc</HostId></Error>

Any ideas what I’m doing wrong?


Submit an answer
You can type!ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

It seems that there is a problem…

My app hangs in this line (when I says hangs I mean that it just doesn’t do anything, no crash’s or printing to the console)

utility.uploadUsingMultiPart(fileURL: url, key: key, contentType: contentType, expression: expression, completionHandler: completion)

All my stuff is correct and there are no errors.

Thanks, Oscar

Yes, AWS S3 is compatible with Space.

Below is example how to setup AWSS3TransferUtility.

var transferUtility: AWSS3TransferUtility!
override func viewDidLoad() {
        // Do any additional setup after loading the view, typically from a nib.
        //Setup credentials
        let credentialsProvider = AWSStaticCredentialsProvider(accessKey:"ACCESS_KEY", secretKey: "SECRET_KEY")
        //Setup region
        let endpoint = AWSEndpoint(urlString: "")

        //Setup the service configuration
        let configuration = AWSServiceConfiguration(region: .USEast1, endpoint: endpoint, credentialsProvider: credentialsProvider)

       //Setup the transfer utility configuration
        let tuConf = AWSS3TransferUtilityConfiguration()
        tuConf.isAccelerateModeEnabled = false
        tuConf.bucket = S3BucketName
        //Register a transfer utility object
            with: configuration!,
            transferUtilityConfiguration: tuConf,
            forKey: "transfer-utility-with-advanced-options"
        //Look up the transfer utility object from the registry to use for your transfers.
        transferUtility = AWSS3TransferUtility.s3TransferUtility(forKey: "transfer-utility-with-advanced-options")

Fixed the issue!

It had to do with the way the SDK was generating the signatures. I’ve submitted the fix.

Here is the following Swift code that will work when the PR is merged. Note: the region doesn’t matter as long as you provide the correct Spaces endpoint and set the service parameter as AWSServiceType.S3.

func setup(accessKey: String, secretKey: String) {
    let accessKey = ""
    let secretKey = ""

    let url = URL(string: "")!
    let endpoint = AWSEndpoint(region: AWSRegionType.USEast1, service: AWSServiceType.S3, url: url)

    let credProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secretKey)
    let serviceConfig = AWSServiceConfiguration(region: .USEast1, endpoint: endpoint, 
    credentialsProvider: credProvider)!

    AWSServiceManager.default()!.defaultServiceConfiguration = serviceConfig

func upload(key: String, url: URL, contentType: String) {
    let utility = AWSS3TransferUtility.default()
    let expression = AWSS3TransferUtilityMultiPartUploadExpression()

    let completion: AWSS3TransferUtilityMultiPartUploadCompletionHandlerBlock = { (task, error) in
                if let error = error {
                } else {
                     print("Successfully uploaded!")

    utility.uploadUsingMultiPart(fileURL: url, key: key, contentType: contentType, expression: expression, completionHandler: completion)

Any updates to this question? I am currently having issues as well using the AWSS3 iOS SDK.

is it work ? i try my ios it does not work

my AppDelegate

   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        UIApplication.shared.statusBarStyle = .lightContent
                                                              didFinishLaunchingWithOptions: launchOptions)

        let endpoint = AWSEndpoint(urlString: "")

        let credentialsProvider = AWSStaticCredentialsProvider(
            secretKey: "LpHUnBsx6MtFsHn59jmUGKt9KCUjqU6+jPY8jG150iE/gBB8"
        let defaultServiceConfiguration = AWSServiceConfiguration(
            region: AWSRegionType.APSoutheast1,
            endpoint: endpoint,
            credentialsProvider: credentialsProvider
        defaultServiceConfiguration?.maxRetryCount = 5
        defaultServiceConfiguration?.timeoutIntervalForRequest = 10
        AWSServiceManager.default().defaultServiceConfiguration = defaultServiceConfiguration
        return true
    @IBAction func uploadImageToAWS(_ sender: Any) {
        if profileImage.image == nil {
            // Do something to wake up user :)
        } else {
            let image = profileImage.image!
            let fileManager = FileManager.default
            let path = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("test3.jpeg")
            let imageData = UIImageJPEGRepresentation(image, 0)
            fileManager.createFile(atPath: path as String, contents: imageData, attributes: nil)
            let fileUrl = NSURL(fileURLWithPath: path)
            let uploadRequest = AWSS3TransferManagerUploadRequest()
            uploadRequest?.bucket = "adda"
            uploadRequest?.key = "test"
            uploadRequest?.contentType = "image/jpeg"
            uploadRequest?.body = (fileUrl as URL?)!
            uploadRequest?.serverSideEncryption = AWSS3ServerSideEncryption.awsKms
            uploadRequest?.uploadProgress = { (bytesSent, totalBytesSent, totalBytesExpectedToSend) -> Void in
                DispatchQueue.main.async(execute: {
                    //                    print("totalBytesSent",totalBytesSent)
                    //                    print("totalBytesExpectedToSend",totalBytesExpectedToSend)
                    //                    self.amountUploaded = totalBytesSent // To show the updating data status in label.
                    //                    self.fileSize = totalBytesExpectedToSend
            let transferManager = AWSS3TransferManager.default()
            transferManager.upload(uploadRequest!).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in
                if task.error != nil {
                    // Error.
                    print("error", task.error?.localizedDescription)
                } else {
                    // Do something with your result.
                    print("No error Upload Done")
                return nil


listObjects failed: [Error Domain=com.amazonaws.AWSServiceErrorDomain Code=3 "(null)" UserInfo={Code=SignatureDoesNotMatch, HostId=1af6c2-sgp1a-sgp, RequestId=tx00000000000000036e4b9-005b596ddb-1af6c2-sgp1a}]

error Optional("The operation couldn’t be completed. (com.amazonaws.AWSServiceErrorDomain error 3.)")```

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<ListBucketResult xmlns="">

Use the TransferUtility class also you will want to set the endpoint to

NSData *dataToUpload = // The data to upload.

AWSS3TransferUtilityUploadExpression *expression = [AWSS3TransferUtilityUploadExpression new];
expression.uploadProgress = ^(AWSS3TransferUtilityTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // Do something e.g. Update a progress bar.

AWSS3TransferUtilityUploadCompletionHandlerBlock completionHandler = ^(AWSS3TransferUtilityUploadTask *task, NSError *error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // Do something e.g. Alert a user for transfer completion.
        // On failed uploads, `error` contains the error object.

AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility];
[[transferUtility uploadFile:fileURL
            completionHander:completionHandler] continueWithBlock:^id(AWSTask *task) {
    if (task.error) {
        NSLog(@"Error: %@", task.error);
    if (task.exception) {
        NSLog(@"Exception: %@", task.exception);
    if (task.result) {
        AWSS3TransferUtilityUploadTask *uploadTask = task.result;
        // Do something with uploadTask.

    return nil;