Thursday, 27 April 2023

AWS S3 Upload multiple files and single file

 import AWSS3

import AWSCore

typealias awsCompletionHandler = (_ isValid:Bool,_ url:String) -> Void


struct AWSConstants{

    static let poolId = ""

    static let bucket = "BucketIdentifier"

    static let accessKeyId = ""

    static let secretAccessKey = ""

    static let region = ""

    

}



class AWS_S3_BucketManager:NSObject{

    static let shared = AWS_S3_BucketManager()

    

    var s3_AccessInfo : AWS_DetailModel?

    

    let bucketName: String = AWSConstants.bucket

    let folderName: String = "FolderOnS3Bucket"

    

    func getAccessToken(completion:@escaping (AWS_APIModel) -> Void){

        NetworkManager.shared.fetch(type: AWS_APIModel.self, httpMethod: .get, isAutorization: true, api: .s3_token, parameter: nil,showLoader: false) { (success, result) in

            Loader.shared.hideLoadingView()

            if success{

                guard let result = result else {return}

                self.s3_AccessInfo = result.data

                // completion(result)

            }

        }

    }

    

    

    func generateRandomStringWithLength(length: Int) -> String {

        let randomString: NSMutableString = NSMutableString(capacity: length)

        let letters: NSMutableString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

        var i: Int = 0

        

        while i < length {

            let randomIndex: Int = Int(arc4random_uniform(UInt32(letters.length)))

            randomString.append("\(Character( UnicodeScalar( letters.character(at: randomIndex))!))")

            i += 1

        }

        return String(randomString)

    }

    

    

    enum MimeType :String{

        case image = "image/*"

        case audio = "audio/*"

    }

    

    

  

    func uploadFileToS3(fileUrl:URL?,contentType:MimeType,completion:@escaping (_ isValid:Bool,_ url:String) -> Void){

        


        guard let url = fileUrl else {  completion(false, "Something went wrong!")

            return  }

        

        guard let accessKey =   AWS_S3_BucketManager.shared.s3_AccessInfo?.AccessKeyId,

              let secretKey = AWS_S3_BucketManager.shared.s3_AccessInfo?.SecretAccessKey, let token = AWS_S3_BucketManager.shared.s3_AccessInfo?.SessionToken else {

            completion(false, "Something went wrong!")

            return

            

        }

                

        let credentialsProvider = AWSBasicSessionCredentialsProvider(accessKey: accessKey, secretKey: secretKey, sessionToken: token)

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

        AWSServiceManager.default().defaultServiceConfiguration = configuration

       

       

        

        let remoteName = folderName+"/\(generateRandomStringWithLength(length: 10))\(url.deletingPathExtension().lastPathComponent).\(url.pathExtension)"

        

        let expression = AWSS3TransferUtilityUploadExpression()

//        expression.setValue("unknown", forRequestParameter: "x-amz-acl")

//        expression.setValue("unknown", forRequestHeader: "x-amz-acl" )

        

        expression.progressBlock  = {(task, progress) in

            print("progress",progress.fractionCompleted)

            if progress.isFinished{

                print("finsihed upload progress")

//                DispatchQueue.main.async {

//                    print("Tassk")

//                    completion(true, remoteName)

//

//                }

            }

        }

        

        let transferUtility =  AWSS3TransferUtility.default()


        Loader.shared.showLoadingView()

        let backgroundQueue = DispatchQueue.global(qos: .background)

        backgroundQueue.async {

            

            transferUtility.uploadFile(url, bucket: self.bucketName, key: remoteName, contentType: contentType.rawValue, expression: expression) { task, error in

                if error != nil {

                    DispatchQueue.main.async {

                        Loader.shared.hideLoadingView()

                        completion(false, "Something went wrong!")

                    }

                } else {

                    print("File uploaded successfully")

                }

                

                // Update progress

                DispatchQueue.main.async {

                    Loader.shared.hideLoadingView()

                    print("Tassk",task)

                    completion(true, remoteName)

                    

                }

                

            }

            

        }

    }

    

    func uploadMultipleFileToS333(fileUrls:[RecordingSelectionModel],viewController:UIViewController,completion:@escaping awsCompletionHandler){

        

        guard (fileUrls.count > 0 ) else {  completion(false, "Something went wrong!")

            return  }

        

        guard let accessKey =   AWS_S3_BucketManager.shared.s3_AccessInfo?.AccessKeyId,

              let secretKey = AWS_S3_BucketManager.shared.s3_AccessInfo?.SecretAccessKey, let token = AWS_S3_BucketManager.shared.s3_AccessInfo?.SessionToken else {

            completion(false, "Something went wrong!")

            return

            

        }

        

        let credentialsProvider = AWSBasicSessionCredentialsProvider(accessKey: accessKey, secretKey: secretKey, sessionToken: token)

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

        AWSServiceManager.default().defaultServiceConfiguration = configuration

        

        let hud = MBProgressHUD.showAdded(to: viewController.view, animated: true)

               hud.mode = .annularDeterminate

               hud.label.text = "Uploading \(fileUrls.count) items"

        

        let transferUtility = AWSS3TransferUtility.default()

        var names = [String]()

        var totalTask = 1

        

        let backgroundQueue = DispatchQueue.global(qos: .background)

        backgroundQueue.async {

            

            // Upload each file using the transfer utility

            for (index,item) in fileUrls.enumerated() {

                // Set the S3 key (file name) for the uploaded file

                if  let url = URL(string: item.media_file ?? "") {

                    var contentType = ""

                    switch  item.media_type{

                    case .image: contentType = "image/*"

                    case .audio: contentType = "audio/*"

                    case .video: contentType = "video/*"

                        

                    case .drawing_board,.check_list,.notes,.shapes:

                        break

                    case .none:

                        break

                    }

                    

                    let remoteName = self.folderName+"/\(self.generateRandomStringWithLength(length: 10))\(url.deletingPathExtension().lastPathComponent).\(url.pathExtension)"

                    

//

                    let mpExpression = AWSS3TransferUtilityMultiPartUploadExpression()

                    mpExpression.progressBlock = {(task, progress) in

                        print("task",task,"progress",progress.fractionCompleted)

                        

                        if task.error != nil {

                          //  debugPrint("Error uploading",task.error.localizedDescription)

                        }else{

                            

                           // debugPrint("Uploaded",remoteName)

                            

                           

                        }

                        

                    }

                  


                    

                    transferUtility.uploadUsingMultiPart(fileURL: url, bucket: self.bucketName, key: remoteName

                                                         , contentType: contentType, expression: mpExpression,completionHandler: { task, error in

                        if task.error != nil {

                            debugPrint("Error uploading Completion",task.error.localizedDescription)

                        }else{

                            debugPrint("Uploaded Completion \(index)",remoteName)

                            names.append(remoteName)

                        }

                       

                        DispatchQueue.main.async {

                          

//                            hud.progress = Float(index + 1) / Float(fileUrls.count)

//                            hud.label.text = "Uploading item \(index + 1) of \(fileUrls.count)"

                            

                                hud.progress = Float(totalTask) / Float(fileUrls.count)

                                totalTask += 1

                                hud.label.text = "Uploading item \(totalTask) of \(fileUrls.count)"

                           

//                            if index == fileUrls.count - 1 {

                            if totalTask == fileUrls.count {

                                hud.hide(animated: true)

                                completion(true,names.joined(separator: ","))

                            }

                        }

                        

                        

                    }).continueWith { task in

                        if task.error != nil{

                            

                            debugPrint("Error S3 ",task.error?.localizedDescription)

//                            debugPrint("Error Code",(task.error as? NSError)?.code)

//                            debugPrint("Error domain:",(task.error? as NSError).errorDomain)

                            

                            DispatchQueue.main.async {   hud.hide(animated: true) }

                        }else{

                            debugPrint("File uploading")

//                            names.append(remoteName)

                            //Task

                            // Update progress

                           

                        }

                      

//                        DispatchQueue.main.async {

//                            hud.progress = Float(index + 1) / Float(fileUrls.count)

//                            hud.label.text = "Uploading item \(index + 1) of \(fileUrls.count)"

//                            if index == fileUrls.count - 1 {

//                                hud.hide(animated: true)

//                                completion(true,names.joined(separator: ","))

//                            }

//                        }

                        

                        return nil

                    }

                    

//                    transferUtility.uploadUsingMultiPart(fileURL: url, bucket: self.bucketName, key: remoteName, contentType: contentType, expression: mpExpression){ task, error in

//

//

//                        if let error = error {

//                            print("Error uploading file: \(error.localizedDescription)")

//                        } else {

//                            print("File uploaded successfully")

//                        }

//

//                        // Update progress

//                        DispatchQueue.main.async {

//                            hud.progress = Float(index + 1) / Float(fileUrls.count)

//                            hud.label.text = "Uploading item \(index + 1) of \(fileUrls.count)"

//                            if index == fileUrls.count - 1 {

//                                hud.hide(animated: true)

//                                completion(true,names.joined(separator: ","))

//                            }

//                        }

//

//                    }

                }

            }

        }

    }

    

    

    

    func uploadMultipleFileToS3(fileUrls:[RecordingSelectionModel],viewController:UIViewController,completion:@escaping awsCompletionHandler){

        

        guard (fileUrls.count > 0 ) else {  completion(false, "Something went wrong!")

            return  }

        

        guard let accessKey =   AWS_S3_BucketManager.shared.s3_AccessInfo?.AccessKeyId,

              let secretKey = AWS_S3_BucketManager.shared.s3_AccessInfo?.SecretAccessKey, let token = AWS_S3_BucketManager.shared.s3_AccessInfo?.SessionToken else {

            completion(false, "Something went wrong!")

            return

            

        }

        

        let credentialsProvider = AWSBasicSessionCredentialsProvider(accessKey: accessKey, secretKey: secretKey, sessionToken: token)

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

        AWSServiceManager.default().defaultServiceConfiguration = configuration

        

        let hud = MBProgressHUD.showAdded(to: viewController.view, animated: true)

               hud.mode = .annularDeterminate

               hud.label.text = "Uploading \(fileUrls.count) items"

        

        let transferUtility = AWSS3TransferUtility.default()

       

       // var totalTask = 1

        selectedIndex = 0

        let backgroundQueue = DispatchQueue.global(qos: .background)

        backgroundQueue.async {

            self.copyFiles = fileUrls

           

            for var item in self.copyFiles{

                item.media_file = ""

            }

            

            // Upload each file using the transfer utility

          

           let uploadGroup = DispatchGroup()

            uploadGroup.enter()

            func awsMultipleUploading(fileUrls:[RecordingSelectionModel]){

                

                self.uploadTaskOnAWS_S3(items:fileUrls) { success, fileName, error in

                   

                    if error == nil{

                        self.copyFiles[self.selectedIndex].media_file = fileName

                    }else{

                        self.copyFiles[self.selectedIndex].media_file = ""

                    }

                    if self.selectedIndex != fileUrls.count-1{

                        

                        debugPrint(self.copyFiles.count, self.selectedIndex)

                        

                        DispatchQueue.main.async {

                            hud.progress = Float(self.selectedIndex) / Float(fileUrls.count)

                            self.selectedIndex += 1

                            hud.label.text = "Uploading item \(self.selectedIndex) of \(fileUrls.count)"

                        }

                        

                        awsMultipleUploading(fileUrls: fileUrls)

                    }else{

                      uploadGroup.leave()

                    }

                } progressCompletion: { value, error in

                    debugPrint("Progress",value,error)

                }

            }

            

           

            awsMultipleUploading(fileUrls: fileUrls)


            uploadGroup.notify(queue: .main) {

                debugPrint("CompletedAll")

                let files = self.copyFiles.map{$0.media_file ?? ""}

                hud.hide(animated: true)

                completion(true,files.joined(separator: ","))

            }

        }

    }

    

    var selectedIndex = 0

    var names = [String]()

    var copyFiles = [RecordingSelectionModel]()

    

   

    

    func uploadTaskOnAWS_S3(items:[RecordingSelectionModel],completionHandler:@escaping((Bool,String,Error?)->Void?),progressCompletion:@escaping((Double,Error?)->Void?)){

        let item = items[selectedIndex]

        let transferUtility = AWSS3TransferUtility.default()

        

        if  let url = URL(string: item.media_file ?? "") {

            var contentType = ""

            switch  item.media_type{

            case .image: contentType = "image/*"

            case .audio: contentType = "audio/*"

            case .video: contentType = "video/*"

                

            case .drawing_board,.check_list,.notes,.shapes:

                break

            case .none:

                break

            }

            

            let remoteName = self.folderName+"/\(self.generateRandomStringWithLength(length: 10))\(url.deletingPathExtension().lastPathComponent).\(url.pathExtension)"

            

//

            let mpExpression = AWSS3TransferUtilityMultiPartUploadExpression()

            mpExpression.progressBlock = {(task, progress) in

              

                print("task",task,"progress",progress.fractionCompleted)

                

                if task.error != nil {

                    progressCompletion(0,task.error)

                  //  debugPrint("Error uploading",task.error.localizedDescription)

                }else{

                    progressCompletion(progress.fractionCompleted,task.error)

                   // debugPrint("Uploaded",remoteName)

                    

                   

                }

                

            }

          


            

            transferUtility.uploadUsingMultiPart(fileURL: url, bucket: self.bucketName, key: remoteName

                                                 , contentType: contentType, expression: mpExpression,completionHandler: { task, error in

                if task.error != nil {

                    debugPrint("Error uploading Completion",task.error.localizedDescription)

                    completionHandler(false, "",task.error)

                }else{

                    debugPrint("Uploaded Completio","remoteName")

                    completionHandler(true, remoteName,task.error)

                }

               

              

                

            }).continueWith { task in

                if task.error != nil{

                    

                    debugPrint("Error S3 ",task.error?.localizedDescription )

                    completionHandler(false,"",task.error!)

                }else{

                    debugPrint("File uploading")


                   

                }


                return nil

            }

            

        }

    }

    

    

    var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?

    

}


////////////////////////--------------------------




import MobileCoreServices

import PhotosUI


extension String {

     func isMediaType() -> UploadMediaType {

        // image formats which you want to check

        let imageFormats = ["jpg", "jpeg", "jfif", "pjpeg", "pjp","gif","ico","tif","tiff","bmp","image","png","HEIC"]

         let audioFormats = ["aiff", "amr", "mp3","m4a","audio"]

         let videoFormats = ["wav", "wmv", "mpeg","3gp","mp4","video"]


         if let urlValue = URL(string: self),

            let mediaType = getMediaType(from: urlValue) , mediaType.isEmpty == false{

             let values = mediaType.components(separatedBy: "/")

             if  let first = values.first?.lowercased(), let last = values.last?.lowercased(){

                 if audioFormats.contains(first) || audioFormats.contains(last){

                     return .audio

                     

                 }

                 if videoFormats.contains(first) || videoFormats.contains(last){

                     return .video

                     

                 }

                 if imageFormats.contains(first) || imageFormats.contains(last){

                     return .image

                     

                 }

             }

         }

         if URL(string: self) != nil{

             let extensi = (self as NSString).pathExtension.lowercased()

             

             if imageFormats.contains(extensi){

                 return .image

             }

         

             if audioFormats.contains(extensi){

                 return .audio

             }

             

             if videoFormats.contains(extensi){

                 return .video

             }

             return .audio

         }else{

             return .audio

         }


    }

    

    func getMediaType(from url: URL) -> String? {

        guard let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, url.pathExtension as CFString, nil)?.takeRetainedValue() else {

            return nil

        }

        return UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() as String?

    }

}


No comments:

Post a Comment