Swift SDK for Sirv S3

On this page

For Swift iOS development, install the AWS SDK for iOS using the CocoaPods AWSS3 pod.

Connect to Sirv

1. First, configure the service:

let accessKey = "ENTER_YOUR_SIRV_S3_KEY_HERE"
let secret = "ENTER_YOUR_SIRV_S3_SECRET_HERE"
let bucket = "ENTER_YOUR_SIRV_S3_BUCKET_HERE"
let endpoint = "https://s3.sirv.com"

var s3: AWSS3!

func configureS3(){
        let credentialsProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secret)

        let configuration = AWSServiceConfiguration(region: AWSRegionType.EUWest2, endpoint: AWSEndpoint(urlString: endpoint), credentialsProvider: credentialsProvider)    
//Any region except .Unknown can be passed
     AWSServiceManager.default().defaultServiceConfiguration = configuration
        
        s3 = AWSS3.default()
    }

2. Then use any of the example scripts below to:

  • List folder contents
  • Get file info & meta
  • Delete file/folder
  • Rename file/folder
  • Move file/folder
  • Copy file/folder
  • Create folder
  • Upload file

List folder contents

Note: to list the root folder contents, leave listObjectsRequest.prefix blank.

    func listBucketObjects() {
        if let listObjectsRequest = AWSS3ListObjectsRequest(){
            listObjectsRequest.bucket = bucket
            listObjectsRequest.prefix = "example/folder/"
            
            s3.listObjects(listObjectsRequest) { (output, error) in
                if let requestError = error{
                    print("List objects request failed with error: \(requestError)")
                } else if let listOutputObjects = output{
                    print("Bucket objects: \(listOutputObjects)")
                }
            }
        }
    }

Get file info & meta

    func fetchFileInfo(){
        if let objectRequest = AWSS3GetObjectRequest(){
            objectRequest.bucket = bucket
            objectRequest.key = "example/folder/image.jpg"
            
            s3.getObject(objectRequest) { (output, error) in
                if let requestError = error{
                    print("Get object request failed with error: \(requestError)")
                } else if let objectContent = output{
                    print("Object data recieved: \(objectContent.contentLength, objectContent.metadata, objectContent.contentType)")
                }
            }
        }
    }

Delete file/folder

Note: if deleting a folder, append "/" to the path.

    func deleteFile(){
        if let deleteRequest = AWSS3DeleteObjectRequest(){
            deleteRequest.bucket = bucket
            deleteRequest.key = "example/folder/image.jpg"
            
            s3.deleteObject(deleteRequest) { (output, error) in
                if let requestError = error{
                    print("Delete request failed with error: \(requestError)")
                } else if output != nil{
                    print("Object \(deleteRequest.key) deleted")
                }
            }
        }
    }

Rename file/folder

To rename a file, copy it, then delete the original.

    func renameFile(){
        if let replicateRequest = AWSS3ReplicateObjectRequest(){
            replicateRequest.bucket = bucket
            replicateRequest.replicateSource = "/(bucket)/folder/original-image.jpg"
            replicateRequest.key = "folder/new-image.jpg"
            
            s3.replicateObject(replicateRequest) { (output, error) in
                if let requestError = error{
                    print("Copy object request failed with error: \(requestError)")
                } else if output != nil{
                    if let deleteRequest = AWSS3DeleteObjectRequest(){
                        deleteRequest.bucket = self.bucket
                        deleteRequest.key = "folder/original-image.jpg"
                        
                        self.s3.deleteObject(deleteRequest) { (output, error) in
                            if let requestError = error{
                                print("Rename request failed with error: \(requestError)")
                            } else if output != nil{
                                print("Object renamed to \(replicateRequest.key)")
                            }
                        }
                    }
                }
            }
        }
    }

Move file/folder

To move a file, copy it, then delete the original.

    func moveFile(){
        if let replicateRequest = AWSS3ReplicateObjectRequest(){
            replicateRequest.bucket = bucket
            replicateRequest.replicateSource = "/(bucket)/original-folder/image.jpg"
            replicateRequest.key = "new-folder/image.jpg"
            
            s3.replicateObject(replicateRequest) { (output, error) in
                if let requestError = error{
                    print("Move object request failed with error: \(requestError)")
                } else if output != nil{
                    if let deleteRequest = AWSS3DeleteObjectRequest(){
                        deleteRequest.bucket = self.bucket
                        deleteRequest.key = "original-folder/image.jpg"
                        
                        self.s3.deleteObject(deleteRequest) { (output, error) in
                            if let requestError = error{
                                print("Delete request failed with error: \(requestError)")
                            } else if output != nil{
                                print("Object moved to \(replicateRequest.key)")
                            }
                        }
                    }
                }
            }
        }
    }

Copy file/folder

    func copyFile(){
        if let replicateRequest = AWSS3ReplicateObjectRequest(){
            replicateRequest.bucket = bucket
            replicateRequest.replicateSource = "/(bucket)/folder/original-image.jpg"
            replicateRequest.key = "folder/new-image.jpg"
            
            s3.replicateObject(replicateRequest) { (output, error) in
                if let requestError = error{
                    print("Copy object request failed with error: \(requestError)")
                } else if output != nil{
                    print("Object copied to: \(replicateRequest.key)")
                }
            }
        }
    }

Create folder

    func createFolder(){
        if let createRequest = AWSS3PutObjectRequest(){
            createRequest.bucket = bucket
            createRequest.key = "example/new-folder-name/"
            
            s3.putObject(createRequest) { (output, error) in
                if let requestError = error{
                    print("Create object request failed with error: \(requestError)")
                } else if output != nil{
                   print("Folder \(createRequest.key) created")
                }
            }
        }

Upload file

Uploads must be signed. The method below will upload a file and sign it using signS3RequestV4.

The compressionQuality value is from 0 to 1 (0% to 100%), where 0.92 will upload images at 92% quality (recommended).

Note: the AWS SDK has other upload methods (putObject and AWSS3TransferUtility uploadFile), though they are not compatible with Sirv yet.

    func uploadFile(){
        let image = UIImage(named: image_name)
        let imageData = image?.jpegData(compressionQuality: 0.92)
        let keyName = "example/folder/image.jpg"

        let request = NSMutableURLRequest(url: URL(string: "(endpoint)/(bucket)/(keyName)")!)
        request.httpMethod = "PUT"
        request.setValue("public-read", forHTTPHeaderField: "x-amz-acl")
        request.httpBody = imageData
        
        let credentialsProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secret)
        credentialsProvider.credentials().continueOnSuccessWith { (task) -> Any? in
            if let credentials = task.result{
                
                let authorization = self.signS3RequestV4(urlRequest: request, credentials: credentials)
                request.setValue(authorization, forHTTPHeaderField:"Authorization")
                
                let uploadTask = URLSession.shared.uploadTask(with: request as URLRequest, from: imageData, completionHandler: { (data, response, error) in
//process response here
                print("File \(keyName) uploaded")
                })
                uploadTask.resume()
            }
            return nil
        }
 }

/* Now sign the upload... */

    func signS3RequestV4(urlRequest : NSMutableURLRequest, credentials: AWSCredentials) -> String{
let awsEndpoint = AWSEndpoint(region: .EUWest2, serviceName: "s3", url: URL(string: endpoint)!)

        urlRequest.setValue(awsEndpoint!.hostName, forHTTPHeaderField: "host")
        
        let date = Date()
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = AWSDateISO8601DateFormat2
        dateFormatter.timeZone = TimeZone(identifier: "UTC")
        let dateStamp = dateFormatter.string(from: date)
        urlRequest.setValue(dateStamp, forHTTPHeaderField: "x-amz-date")
        
        let dateFormatterShort = DateFormatter()
        dateFormatterShort.dateFormat = AWSDateShortDateFormat1
        let dateStampShort = dateFormatterShort.string(from: date)
    
        let scope = String(format: "%@/%@/%@/%@", dateStampShort, awsEndpoint!.regionName, (awsEndpoint?.serviceName)!, AWSSignatureV4Terminator)
        let signingCredentials = String(format: "%@/%@", credentials.accessKey, scope)
        
        let httpMethod = urlRequest.httpMethod
        let path = urlRequest.url!.path
        let query = urlRequest.url?.query ?? ""
        
        let contentSha256 = AWSSignatureSignerUtility.hexEncode(String(data: AWSSignatureSignerUtility.hash(urlRequest.httpBody), encoding: String.Encoding.ascii))
        urlRequest.setValue(contentSha256, forHTTPHeaderField: "x-amz-content-sha256")
        
        let headers = urlRequest.allHTTPHeaderFields
        let canonicalRequest = AWSSignatureV4Signer.getCanonicalizedRequest(httpMethod, path: path, query: query, headers: headers, contentSha256: contentSha256)
        
        let stringToSign = String(format: "%@\n%@\n%@\n%@",
                                  AWSSignatureV4Algorithm,
                                  urlRequest.value(forHTTPHeaderField: "x-amz-date")!,
                                  scope, AWSSignatureSignerUtility.hexEncode(AWSSignatureSignerUtility.hashString(canonicalRequest)))
        print("AWS4 String to Sign \(stringToSign)")
        
        let kSigning = AWSSignatureV4Signer.getV4DerivedKey(credentials.secretKey, date: dateStampShort, region: awsEndpoint?.regionName, service: awsEndpoint?.serviceName)
        
        let signature = AWSSignatureSignerUtility.sha256HMac(with: stringToSign.data(using: String.Encoding.utf8), withKey: kSigning)
        let signatureString = AWSSignatureSignerUtility.hexEncode(String(data: signature!, encoding: String.Encoding.ascii))
        let authorization = String(format: "%@ Credential=%@, SignedHeaders=%@, Signature=%@",
            AWSSignatureV4Algorithm,
            signingCredentials,
            AWSSignatureV4Signer.getSignedHeadersString(headers), signatureString!)
        
        return authorization
    }

Was this article helpful?

Related articles

Get help from a Sirv expert