我在应用程序中将Amazon S3用作文件存储系统。我所有的item对象都有几个与之关联的图像,并且每个对象仅存储图像URL,以保持数据库的轻量化。因此,我需要一种有效的方法直接从iOS将多个图像上传到S3,并在成功完成后将它们的URL存储在我发送给服务器的对象中。我仔细研究了Amazon提供的SDK和示例应用程序,但是我遇到的唯一示例是单个图像上传,操作如下:
func uploadData(data: NSData) { let expression = AWSS3TransferUtilityUploadExpression() expression.progressBlock = progressBlock let transferUtility = AWSS3TransferUtility.defaultS3TransferUtility() transferUtility.uploadData( data, bucket: S3BucketName, key: S3UploadKeyName, contentType: "text/plain", expression: expression, completionHander: completionHandler).continueWithBlock { (task) -> AnyObject! in if let error = task.error { NSLog("Error: %@",error.localizedDescription); self.statusLabel.text = "Failed" } if let exception = task.exception { NSLog("Exception: %@",exception.description); self.statusLabel.text = "Failed" } if let _ = task.result { self.statusLabel.text = "Generating Upload File" NSLog("Upload Starting!") // Do something with uploadTask. } return nil; } }
对于5张以上的图片,这将成为一团糟,因为我必须等待每次上传成功返回后才能启动下一个,然后最终将对象发送到我的数据库。我是否需要有效,干净的代码来实现自己的目标?
亚马逊示例应用程序github的URL:https : //github.com/awslabs/aws-sdk-ios-samples/tree/master/S3TransferUtility-Sample/Swift
这是我用来同时将多个图像上传到S3的代码DispatchGroup()
。
func uploadOfferImagesToS3() { let group = DispatchGroup() for (index, image) in arrOfImages.enumerated() { group.enter() Utils.saveImageToTemporaryDirectory(image: image, completionHandler: { (url, imgScalled) in if let urlImagePath = url, let uploadRequest = AWSS3TransferManagerUploadRequest() { uploadRequest.body = urlImagePath uploadRequest.key = ProcessInfo.processInfo.globallyUniqueString + "." + "png" uploadRequest.bucket = Constants.AWS_S3.Image uploadRequest.contentType = "image/" + "png" uploadRequest.uploadProgress = {(bytesSent:Int64, totalBytesSent:Int64, totalBytesExpectedToSend:Int64) in let uploadProgress = Float(Double(totalBytesSent)/Double(totalBytesExpectedToSend)) print("uploading image \(index) of \(arrOfImages.count) = \(uploadProgress)") //self.delegate?.amazonManager_uploadWithProgress(fProgress: uploadProgress) } self.uploadImageStatus = .inProgress AWSS3TransferManager.default() .upload(uploadRequest) .continueWith(executor: AWSExecutor.immediate(), block: { (task) -> Any? in group.leave() if let error = task.error { print("\n\n=======================================") print("? Upload image failed with error: (\(error.localizedDescription))") print("=======================================\n\n") self.uploadImageStatus = .failed self.delegate?.amazonManager_uploadWithFail() return nil } //=> Task completed successfully let imgS3URL = Constants.AWS_S3.BucketPath + Constants.AWS_S3.Image + "/" + uploadRequest.key! print("imgS3url = \(imgS3URL)") NewOfferManager.shared.arrUrlsImagesNewOffer.append(imgS3URL) self.uploadImageStatus = .completed self.delegate?.amazonManager_uploadWithSuccess(strS3ObjUrl: imgS3URL, imgSelected: imgScalled) return nil }) } else { print(" Unable to save image to NSTemporaryDirectory") } }) } group.notify(queue: DispatchQueue.global(qos: .background)) { print("All \(arrOfImages.count) network reqeusts completed") } }
这是关键部分,我至少损失了5个小时。NSTemporaryDirectory
每个图片的 URL都必须不同!
class func saveImageToTemporaryDirectory(image: UIImage, completionHandler: @escaping (_ url: URL?, _ imgScalled: UIImage) -> Void) { let imgScalled = ClaimitUtils.scaleImageDown(image) let data = UIImagePNGRepresentation(imgScalled) let randomPath = "offerImage" + String.random(ofLength: 5) let urlImgOfferDir = URL(fileURLWithPath: NSTemporaryDirectory().appending(randomPath)) do { try data?.write(to: urlImgOfferDir) completionHandler(urlImgOfferDir, imgScalled) } catch (let error) { print(error) completionHandler(nil, imgScalled) } }
希望这会有所帮助!