处理多个文件(图像)上传到AWS S3 Swift

时间:2018-02-04 00:26:01

标签: ios swift amazon-s3

我一直在尝试研究从iOS应用上传多个图像到AWS S3的最佳方法。我已经在StackOverflow上看到了一些类似的问题,并且对#34;答案"在这里:link。虽然我不完全理解线程/调度组/等,但我尝试了很多方法来实现上传多个图像的方法。我是如何想象的那样:

  1. 上传多张图片的通话方式&传递多个图像
  2. 遍历图像,通过调用特殊方法创建新的AWS S3上传请求(在调用前输入调度组)
  3. 在upload方法中使用完成处理程序,如果成功/错误发生,则返回true / false(在完成处理程序中,离开调度组)
  4. 等待调度组任务完成,然后使用notify处理后续步骤
  5. 我在这些方面创造了类似的东西;然而,它似乎没有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;
        }
    }
    

    另外 - 如果对这个问题有更好的解决方法,我会很好奇。而不是创建要上传的项目列表,然后迭代(x次基于retryCount),尝试上传项目(并删除那些成功的项目),然后向用户显示结果(如果是全有或全无, 1张图片无法上传)。是否有更好的用户体验/效率途径?谢谢!

0 个答案:

没有答案