alionthego
alionthego

Reputation: 9703

iOS image upload to AWS S3 Bucket very slow

I am trying to upload images to an AWS S3 bucket from my iOS app using the AWS SDK. I use the following method to upload the image:

func uploadMedia(mediaData: Data, mediaID: String) {

        let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.SomeRegion,
                                                                identityPoolId:"my identity pool ...")
        let configuration = AWSServiceConfiguration(region:.SomeRegion, credentialsProvider:credentialsProvider)
        AWSServiceManager.default().defaultServiceConfiguration = configuration

        let transferManager = AWSS3TransferManager.default()

        let uploadingFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(mediaID)
        do {
            try mediaData.write(to: uploadingFileURL, options: Data.WritingOptions.atomic)
        } catch let error as NSError {
            print("Could not save \(error), \(error.userInfo)")
        }

        let uploadRequest = AWSS3TransferManagerUploadRequest()!

        uploadRequest.bucket = "myBucket"
        uploadRequest.key = mediaID + ".jpg"
        uploadRequest.body = uploadingFileURL
        uploadRequest.contentType = "image/jpeg"

        transferManager.upload(uploadRequest).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in

            if let error = task.error as NSError? {
                if error.domain == AWSS3TransferManagerErrorDomain, let code = AWSS3TransferManagerErrorType(rawValue: error.code) {
                    switch code {
                    case .cancelled, .paused:
                        break
                    default:
                        print("Error uploading: \(uploadRequest.key!) Error: \(error)")
                    }
                } else {
                    print("Error uploading: \(uploadRequest.key!) Error: \(error)")
                }
                return nil
            }

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

The upload is successful but it takes significantly longer than just uploading via PHP script to a directory in my EC2 instance. Even for small files just 30 KB or so it takes a few seconds longer. I have turned off the default server encryption but that didn't help much.

Am I using the SDK correctly to upload the image data? The data is stored locally in coreData and extracted as Data rather than an image file. That's why I make a temporary directory to create the url for upload.

Upvotes: 2

Views: 1301

Answers (1)

alionthego
alionthego

Reputation: 9703

Here is the code that worked based on sqlbot's comment: The configuration and transfer manager definitions are moved to the initializer for the helper class. If picture files are stored in the document file system then creating a temporary file will also not be needed gaining further advantage however I use coreData so need to keep that.

initialize an instance of MediaHelper (let mediaHelper = MediaHelper()) early on in your viewController and maintain a reference to it so that the initialization is done early on and only once.

class MediaHelper {

    var transferManager: AWSS3TransferManager!

    init() {
        let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.SomeRegion,
                                                                identityPoolId:"my identity pool ...")
        let configuration = AWSServiceConfiguration(region:.SomeRegion, credentialsProvider:credentialsProvider)
        AWSServiceManager.default().defaultServiceConfiguration = configuration

        self.transferManager = AWSS3TransferManager.default()
    }

    func uploadMedia(mediaData: Data, mediaID: String) {

        let uploadingFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(mediaID)
        do {
            try mediaData.write(to: uploadingFileURL, options: Data.WritingOptions.atomic)
        } catch let error as NSError {
            print("Could not save \(error), \(error.userInfo)")
        }

        let uploadRequest = AWSS3TransferManagerUploadRequest()!

        uploadRequest.bucket = "myBucket"
        uploadRequest.key = mediaID + ".jpg"
        uploadRequest.body = uploadingFileURL
        uploadRequest.contentType = "image/jpeg"

        transferManager.upload(uploadRequest).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in

            if let error = task.error as NSError? {
                if error.domain == AWSS3TransferManagerErrorDomain, let code = AWSS3TransferManagerErrorType(rawValue: error.code) {
                    switch code {
                    case .cancelled, .paused:
                        break
                    default:
                        print("Error uploading: \(uploadRequest.key!) Error: \(error)")
                    }
                } else {
                    print("Error uploading: \(uploadRequest.key!) Error: \(error)")
                }
                return nil
            }

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

}

Upvotes: 1

Related Questions