我一直在尝试研究从 iOS 应用程序上传多个图像到 AWS S3 的最佳方法。我在 StackOverflow 上看到过一些类似的问题,其中最接近“答案”的问题就在这里:link https://stackoverflow.com/questions/41705839/efficient-way-to-upload-multiple-images-to-s3-from-ios。虽然我不完全理解线程/调度组/等,但我尝试了很多方法来实现上传多个图像的方法。我的设想是这样的:
- 调用方法上传多张图片并传入多张图片
- 迭代图像,通过调用特殊方法创建新的AWS S3上传请求(调用前输入调度组)
- 在上传方法中使用完成处理程序根据是否发生成功/错误返回 true/false(在完成处理程序中,离开调度组)
- 等待调度组任务完成,然后使用通知处理后续步骤
我沿着这些思路创造了类似的东西;然而,它似乎并没有 100% 发挥作用。我已经实现了一个 while 循环来检查“retryCount”,在警告用户上传请求不成功之前尝试 x 次。下面是我目前拥有的代码 - 请告诉我这是否正确处理流程/正确处理大量请求/等等。非常感谢!
static func uploadImages(imagesToUpload: [UIImage], complete: @escaping (String?) -> ()) {
let folderKey = UUID().uuidString
var retryArray = [String: Data]()
var retryCount = 0
for i in 0..<imagesToUpload.count {
retryArray.updateValue(UIImagePNGRepresentation(imagesToUpload[i])!, forKey: "image\(i)")
//retryArray["image\(i)"] = UIImagePNGRepresentation(imagesToUpload[i])
}
let imageGroup = DispatchGroup()
imageGroup.enter()
if(retryArray.keys.count > 0) {
while(retryCount < 3) {
//Iterate through retry array
let uploadGroup = DispatchGroup()
for (key, val) in retryArray {
print("Trying to upload: \(key)")
uploadGroup.enter()
singleUpload(imageToUpload: val, keyVal: "public/\(folderKey)/\(key).png", complete: { (err) -> Void in
//If no error, remove key/value pair
if(!err) {
print("\(key) was successfully uploaded")
retryArray.removeValue(forKey: key)
}
uploadGroup.leave()
})
}
uploadGroup.wait()
if(retryArray.keys.count == 0) {
break
} else {
retryCount = retryCount + 1
}
}
imageGroup.leave()
} else {
imageGroup.leave()
}
imageGroup.notify(queue: DispatchQueue.main) {
if(retryArray.keys.count > 0) {
print("the images could not be uploaded")
complete(nil)
//execute code to delete folder in aws s3
} else {
print("all images uploaded successfully")
complete(folderKey)
}
}
}
static func singleUpload(imageToUpload: Data, keyVal: String, complete: @escaping (Bool) -> ()) {
var data: Data = Data() // Data to be uploaded
data = imageToUpload
let expression = AWSS3TransferUtilityUploadExpression()
var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
completionHandler = { (task, error) -> Void in
//DispatchQueue.main.async(execute: {
if let error = error {
complete(true)
}
else{
complete(false)
}
//})
}
let transferUtility = AWSS3TransferUtility.default()
transferUtility.uploadData(data,
bucket: s3BucketName,
key: keyVal,
contentType: "image/png",
expression: expression,
completionHandler: completionHandler).continueWith {
(task) -> AnyObject! in
if let error = task.error {
print("Error: \(error.localizedDescription)")
complete(true)
}
if let _ = task.result {
// Do something with uploadTask.
}
return nil;
}
}
另外 - 我很好奇是否有更好的方法来解决这个问题。不是创建要上传的项目列表,而是迭代(基于 retryCount x 次),尝试上传项目(并删除成功的项目),然后向用户呈现结果(如果 1,则全有或全无)图片未上传)。有没有更好的用户体验/效率途径?谢谢你!