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?
}
}