2017-01-17 6 views
2

私はAmazon S3をアプリケーションのファイルストレージシステムとして使用しています。すべてのアイテムオブジェクトには複数のイメージが関連付けられており、それぞれにデータベースを軽量に保つためのイメージURLのみが格納されます。そのため、iOSから複数の画像を直接S3にアップロードする効率的な方法が必要です。また、正常終了すると、私はサーバーに送信するオブジェクトにURLを保存します。私は、Amazonが提供するSDKとサンプルアプリを閲覧しましたが、私が遭遇した唯一の例では、単一の画像のアップロードのためのものであり、次のように行く:複数の画像をiOSからS3に効率的にアップロードする

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枚の画像の上向きの場合、これは、ネストされたになります私は各アップロードが正常に戻るのを待ってから次のページを開始してから、最後にそのオブジェクトを自分のDBに送信する必要があるからです。私の目標を達成するための効率的でコードクリーンな方法がありますか? Amazonのサンプルアプリのgithubのに

URL:https://github.com/awslabs/aws-sdk-ios-samples/tree/master/S3TransferUtility-Sample/Swift

+0

あなたはそれを解決しましたか?私は同じことを探しています。 – user2722667

答えて

1

のは、あなたがたNSDataの配列があるとしましょう、あなたのコードは次のようになります。単純に一連のデータを繰り返して一度にアップロードするだけです。

Javascriptには、配列の個々の要素に対してバックグラウンド操作を行い、それぞれが終了したときと配列全体が終了したときにコールバックを取得するライブラリ(Async.jsだと思います)があります。私はSwiftのようなものは認識していないので、アップロードを連鎖させるというあなたの直感は正しいです。

@DavidTamrazovがコメントで説明したように、再帰を使用して呼び出しを連鎖させることができます。この問題を解決する方法は、ネットワーク操作がNSOperationQueueを使用してNSOperationsを使用して行われるため、もう少し複雑です。配列の最初のイメージをアップロードするカスタムNSOperationに一連のイメージを渡します。それが完了すると、NSOperationsQueueに残りのイメージの配列を持つ別のNSOperationが追加されます。配列に画像がなくなると、私は完全であることを知っています。

以下は、私が使っているはるかに大きなチャンクから抜き出した例です。私はそれを大きく編集し、それをコンパイルする時間がなかったので、疑似コードとして扱います。しかし、うまくいけば、NSOperationsでこれをどうやって行うのかという枠組みについては十分に分かります。

class NetworkOp : Operation { 
    var isRunning = false 

    override var isAsynchronous: Bool { 
     get { 
      return true 
     } 
    } 

    override var isConcurrent: Bool { 
     get { 
      return true 
     } 
    } 

    override var isExecuting: Bool { 
     get { 
      return isRunning 
     } 
    } 

    override var isFinished: Bool { 
     get { 
      return !isRunning 
     } 
    } 

    override func start() { 
     if self.checkCancel() { 
      return 
     } 
     self.willChangeValue(forKey: "isExecuting") 
     self.isRunning = true 
     self.didChangeValue(forKey: "isExecuting") 
     main() 
    } 

    func complete() { 
     self.willChangeValue(forKey: "isFinished") 
     self.willChangeValue(forKey: "isExecuting") 
     self.isRunning = false 
     self.didChangeValue(forKey: "isFinished") 
     self.didChangeValue(forKey: "isExecuting") 
     print("Completed net op: \(self.className)") 
    } 

    // Always resubmit if we get canceled before completion 
    func checkCancel() -> Bool { 
     if self.isCancelled { 
      self.retry() 
      self.complete() 
     } 
     return self.isCancelled 
    } 

    func retry() { 
     // Create a new NetworkOp to match and resubmit since we can't reuse existing. 
    } 

    func success() { 
     // Success means reset delay 
     NetOpsQueueMgr.shared.resetRetryIncrement() 
    } 
} 

class ImagesUploadOp : NetworkOp { 
    var imageList : [PhotoFileListMap] 

    init(imageList : [UIImage]) { 
     self.imageList = imageList 
    } 

    override func main() { 
     print("Photos upload starting") 
     if self.checkCancel() { 
      return 
     } 

     // Pop image off front of array 
     let image = imageList.remove(at: 0) 

     // Now call function that uses AWS to upload image, mine does save to file first, then passes 
     // an error message on completion if it failed, nil if it succceeded 
     ServerMgr.shared.uploadImage(image: image, completion: { errorMessage) in 
      if let error = errorMessage { 
       print("Failed to upload file - " + error) 
       self.retry() 
      } else { 
       print("Uploaded file") 
       if !self.isCancelled { 
        if self.imageList.count == 0 { 
         // All images done, here you could call a final completion handler or somthing. 
        } else { 
         // More images left to do, let's put another Operation on the barbie:) 
         NetOpsQueueMgr.shared.submitOp(netOp: ImagesUploadOp(imageList: self.imageList)) 
        } 
       } 
      } 
      self.complete() 
     }) 
    } 

    override func retry() { 
     NetOpsQueueMgr.shared.retryOpWithDelay(op: ImagesUploadOp(form: self.form, imageList: self.imageList)) 
    } 
} 


// MARK: NetOpsQueueMgr ------------------------------------------------------------------------------- 

class NetOpsQueueMgr { 
    static let shared = NetOpsQueueMgr() 

    lazy var opsQueue :OperationQueue = { 
     var queue = OperationQueue() 
     queue.name = "myQueName" 
     queue.maxConcurrentOperationCount = 1 
     return queue 
    }() 

    func submitOp(netOp : NetworkOp) { 
     opsQueue.addOperation(netOp) 
    } 

    func uploadImages(imageList : [UIImage]) { 
     let imagesOp = ImagesUploadOp(form: form, imageList: imageList) 
     self.submitOp(netOp: imagesOp) 
    } 
} 
+1

これは既存のSwiftクラスをうまく活用する素晴らしいオプションです。ありがとうございます!私は引数として画像の配列をとった再帰関数を使用して終了し、渡された配列が空になると終了するロジックに似ていました。私は、一貫性を保証するためにイメージのアップロードが成功した場合にのみ再発します。 –

+0

ありがとう@DavidTamrazov、あなたはそれが唯一の方法ではないということは間違いありません。実際にあなたがやったやり方は、より簡単で、より良い例です。私はそれに言及するために私の答えを更新するつもりです。 –

-2

はなぜたびにアップロードしたい画像を、それを渡して、ループ内でuploadData()を呼び出していませんか?私はH.アル・アムリの応答に言ったように、あなたが最後のアップロードがすることができます完了したときに知っておく必要がある場合は、

for imgData in array { 
    uploadData(data: imgData) 
} 
+0

これは間違っています – WestonE

+2

これは間違っています。アレイの繰り返し処理が完了すると、すべてのアップロードが開始されたものの、一部またはすべてが完了していないためです。彼らはバックグラウンドで継続し、最後のものがいつ終了するかはわかりません。 –

+0

あなたの方法は間違っています。 –

関連する問題