Swift SDK for Sirv S3
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 }