Search code examples
iosamazon-s3awss3transfermanager

Trying to upload audio to AWS S3 bucket using method(AWSS3TransferUtility). Pod - AWSS3


We are trying to upload audio to AWS S3 bucket using method(AWSS3TransferUtility). Pod - AWSS3. We are getting below error.

Error description:

Error Domain=com.amazonaws.AWSS3TransferUtilityErrorDomain Code=2 "(null)" UserInfo={Server=AmazonS3, Transfer-Encoding=Identity, Connection=close, Content-Type=application/xml, Date=Fri, 06 Sep 2021 04:43:50 GMT, x-amz-request-id=VH53PCCWA529FDRC, x-amz-id-2=4uZoqJj+TJ93WUBSnrC889CAj3gkGGw/V6iJjhrVjB2+ZygTflGcPAV+amfxmeBGeGHHVXv3nHk=}

func uploadFile(withImage image: UIImage) {

    let credentialsProvider = AWSCognitoCredentialsProvider(regionType:AWSRegionType.USEast2,

                                                            identityPoolId:"us-east-2:fe41c293-df49-49a4-886d-094f2cd8d0fd")

    let configuration = AWSServiceConfiguration(region:.USEast2, credentialsProvider:credentialsProvider)

    let tuConf = AWSS3TransferUtilityConfiguration()

    AWSS3TransferUtility.register(

        with: configuration!,

        transferUtilityConfiguration: tuConf,

        forKey: "transfer-utility-with-advanced-options"

    )

    let transferUtility = AWSS3TransferUtility.s3TransferUtility(forKey: "transfer-utility-with-advanced-options")

    AWSServiceManager.default().defaultServiceConfiguration = configuration

    let s3BucketName = "testingimageupload"

    let data: Data = image.pngData()!

    let remoteName = generateRandomStringWithLength(length: 12)+"."+"png"

    print("REMOTE NAME : ",remoteName)

    let expression = AWSS3TransferUtilityUploadExpression()

    expression.setValue("public-read", forRequestHeader: "x-amz-acl")

    expression.progressBlock = { (task, progress) in

        DispatchQueue.main.async(execute: {

            // Update a progress bar

        })

    }

    var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?

    completionHandler = { (task, error) -> Void in

        DispatchQueue.main.async(execute: {

            

        })

    }

    transferUtility!.uploadData(data, bucket: s3BucketName, key: "private/Abhay/" + remoteName, contentType: "image/"+"png", expression: expression, completionHandler: completionHandler).continueWith { (task) -> Any? in

        if let error = task.error {

            print("Error : \(error.localizedDescription)")

        }

        

        if task.result != nil {

            let url = AWSS3.default().configuration.endpoint.url

            let publicURL = url?.appendingPathComponent(s3BucketName).appendingPathComponent(remoteName)

            if let absoluteString = publicURL?.absoluteString {

                // Set image with URL

                print("Image URL : ",absoluteString)

            }

        }

        return nil

    }

Solution

  • Prerequisite : Setup AWS Amplify CLI.

    1. Project initialisation.


    amplify init: Setup AWS Amplify locally & remote.

    Note: amplify init command not found

    1)`npm install -g @aws-amplify/cli` - ### install the Amplify CLI ###
    2)`curl -sL https://aws-amplify.github.io/amplify-cli/install | bash && $SHELL` ### configured $Path correctly ###
    3)`amplify init` ###Try Amplify init###
    

    Amplify Demo project or click enter for the default name : Enter a name for the project

    Dev or click enter for the default name : Enter a name for the Environment

    Choose Visual Studio Code : Choose your default Editor

    iOS : Choose the type of app that you’re building

    yes : Do you want to use an AWS Profile?

    2. Project Storage setup

    amplify add storage : Add storage

    Content(Images, audio, video, etc.) : Select the below mentioned services

    yes : (Amazon Cognito) Do you want to add auth now?

    No: Do you want to configure advanced settings?

    bucket name or click enter for the default name : Please provide bucket name

    Auth users only or Auth and guest users : Who should have access

    create/update , read , delete. : What kind of access do you want for Authenticated users?

    create/update , read , delete.: What kind of access do you want for guest users?

    No : Do you want add a lama trigger for your S3 Bucket?

    3. Push - Amplify configuration to backend

    amplify push : Amplify Push

    Yes: are you sure you want to continue ?

    Pod install

    target ‘ProjectName do
      use_frameworks!
      pod 'Amplify'
      pod 'AmplifyPlugins/AWSS3StoragePlugin'
      pod 'AmplifyPlugins/AWSCognitoAuthPlugin'
    end
    

    Code: ViewController.swift

    import Amplify
    import AmplifyPlugins
    
    func configureAmplify() {
            do {
                try Amplify.add(plugin: AWSCognitoAuthPlugin())
                try Amplify.add(plugin: AWSS3StoragePlugin())
                try Amplify.configure()
                print("Successfully configured Amplify")
            } catch  {
                print("Could not configure Amplify", error)
            }
        }
    func uploadFile() {
            let audioUrl = URL(string: "/Users/appaiah/Downloads/RealAudio.mp3")!
            Amplify.Storage.uploadFile(key: fileKey, local: audioUrl){          // let fileKey = "SampleAudio.mp3"
                result in
                switch result {
                case .success(let key):
                    print("file with key uploaded \(key)")
                case .failure(let error):
                    print("failed \(error)")
                }
            }
        }
    
    
    func downloadFile(){
                        let downloadToFileName = getTermsOfUseURL()     
                        Amplify.Storage.downloadFile(
                            key: fileKey,
                            local: downloadToFileName,
                            progressListener: { progress in
                                print("Progress: \(progress)")
                            }, resultListener: { event in
                                switch event {
                                case .success:
                                    print("Completed")
                                    DispatchQueue.main.async {  }
                                case .failure(let storageError):
                                    print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
                                }
                            })
                    }
        func getTermsOfUseURL() -> URL {
                let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
                print(paths[0].appendingPathComponent(fileKey))
                return paths[0].appendingPathComponent(fileKey)
            }