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
}