iOS App Development iOS Swift Tutorial

iOS App Development : Upload images to AWS S3

In this iOS App Development tutorial series we will learn how to upload images to AWS S3 from you iOS apps.

What we will cover

  • ) Create Amazon Cognito account
  • ) Uploading image to Amazon S3

Amazon Cognito

If we need the functionality to upload images or any other assets to Amazon S3 we add the AWS id and AWS secret to the app. As we know this is not the best approach for security purposes. Amazon recently added Amazon Cognito which tries to solve the problem.

Create a pool

images

Set permission for Authentication Roles as below.

images

AWS setup in the Iphone App.

The next thing we need to do is setup the AWS credentials in the iphone app. We will setup the credentials in the AppDelegate.swift.

//
//  AppDelegate.swift
//  picbucket
//
//  Created by Shrikar Archak on 11/1/14.
//  Copyright (c) 2014 Shrikar Archak. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    let cognitoAccountId = "xxxxxxxxxxxxxxxxx"
    let cognitoIdentityPoolId = "xxxxxxxxxxxxxxxxx"
    let cognitoUnauthRoleArn = "xxxxxxxxxxxxxxxxx"
    let cognitoAuthRoleArn = "xxxxxxxxxxxxxxxxx"

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        let credentialsProvider = AWSCognitoCredentialsProvider.credentialsWithRegionType(
            AWSRegionType.USEast1,
            accountId: cognitoAccountId,
            identityPoolId: cognitoIdentityPoolId,
            unauthRoleArn: cognitoUnauthRoleArn,
            authRoleArn: cognitoAuthRoleArn)
        let defaultServiceConfiguration = AWSServiceConfiguration(
            region: AWSRegionType.USEast1,
            credentialsProvider: credentialsProvider)
        AWSServiceManager.defaultServiceManager().setDefaultServiceConfiguration(defaultServiceConfiguration)

        return true
    }

    func applicationWillResignActive(application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(application: UIApplication) {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
}

If you want to upload an image with name image to Amazon s3 we do it as mentioned below.

let transferManager = AWSS3TransferManager.defaultS3TransferManager()
    let testFileURL1 = NSURL(fileURLWithPath: NSTemporaryDirectory().stringByAppendingPathComponent("temp"))
    let uploadRequest1 : AWSS3TransferManagerUploadRequest = AWSS3TransferManagerUploadRequest()

    let data = UIImageJPEGRepresentation(image, 0.5)
    data.writeToURL(testFileURL1!, atomically: true)
    uploadRequest1.bucket = "shrikar-picbucket"
    uploadRequest1.key =  "bingo"
    uploadRequest1.body = testFileURL1

    let task = transferManager.upload(uploadRequest1)
    task.continueWithBlock { (task) -> AnyObject! in
        if task.error != nil {
            println("Error: \(task.error)")
        } else {
            println("Upload successful")
        }
        return nil
    }

Similarly if you want to read an image from Amazon S3 with name bingo use the code below

    let downloadingFilePath1 = NSTemporaryDirectory().stringByAppendingPathComponent("temp-download")
    let downloadingFileURL1 = NSURL(fileURLWithPath: downloadingFilePath1 )
    let transferManager = AWSS3TransferManager.defaultS3TransferManager()


    let readRequest1 : AWSS3TransferManagerDownloadRequest = AWSS3TransferManagerDownloadRequest()
    readRequest1.bucket = "shrikar-picbucket"
    readRequest1.key =  "bingo"
    readRequest1.downloadingFileURL = downloadingFileURL1

    let task = transferManager.download(readRequest1)
    task.continueWithBlock { (task) ->; AnyObject! in
        println(task.error)
        if task.error != nil {
        } else {
            dispatch_async(dispatch_get_main_queue()
                , { () ->; Void in
                    self.selectedImage.image = UIImage(contentsOfFile: downloadingFilePath1)
                    self.selectedImage.setNeedsDisplay()
                    self.selectedImage.reloadInputViews()

            })
            println("Fetched image")
        }
        return nil
    }

If you keep getting permission error make sure you have setup the permission properly in the IAM Roles created.Github didn’t allow me to add framework . So you might want to explicitly add by following the link Amazon IOS Dependencies and the completed github code is available here
Picbucket.
Learn how to build a complete Trivia App

About the author

Shrikar

Backend/Infrastructure Engineer by Day. iOS Developer for the rest of the time.

  • Mahesh

    I am successfully uploaded image in to S3bucket and getting url from that image when iam browsing that url image is displaying when iam using that url in my Xcode it is not converted in to data I tried following code in swift language i
    s there any mistake in permissions in AWSS3bucket?

    let url = NSURL(string: imageUrl)
    let responseData = NSData(contentsOfURL: url!,options: nil,error:nil)
    print(“The data is (responseData)”)
    changeImgVC.image = UIImage(data:responseData!)

  • Gaurav Sinha

    Thanks for POST, I used AWS to upload images, i got success to upload image but strange after 2-3 images upload i am getting this : Error Domain=NSURLErrorDomain Code=-1003 “The operation couldn’t be completed. (NSURLErrorDomain error -1003.)” UserInfo=0x1742e1780 {NSErrorFailingURLStringKey=https://cognito-identity.ap-southeast-1.amazonaws.com/, NSErrorFailingURLKey=https://cognito-identity.ap-southeast-1.amazonaws.com/, _kCFStreamErrorDomainKey=12, _kCFStreamErrorCodeKey=8, NSUnderlyingError=0x174641680 “The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1003.)” . And it always does after 2-4 images upload successfully, please help.

  • Heshjith

    If image uploaded is jpeg then it is always better to set the contentType to “image/jpeg” or any other image type. Otherwise the content is considered as binary. This created problem when i used AlamofireImage

  • Darren Koong

    Hi Sir, I have created the Cognito Identity Pool in Amazon. How can I retrieve my Identity Pool Id. I am new to AWS. Thank you