theDC
theDC

Reputation: 6484

AWS S3 iOS SDK: How to resume upload after connection is interrupted?

This is my code to accomplish the upload task:

let image = UIImage(named: "12.jpeg")
let fileManager = FileManager.default
let imageData = UIImageJPEGRepresentation(image!, 0.99)
let path = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("\(imageData!).jpeg")

fileManager.createFile(atPath: path as String, contents: imageData, attributes: nil)

let fileUrl = NSURL(fileURLWithPath: path)

uploadRequest?.bucket = "testrawdata"
uploadRequest?.key = "test/loodfd.jpeg"
uploadRequest?.contentType = "image/jpeg"
uploadRequest?.body = fileUrl as URL!
uploadRequest?.serverSideEncryption = AWSS3ServerSideEncryption.awsKms
uploadRequest?.uploadProgress = { (bytesSent, totalBytesSent, totalBytesExpectedToSend) -> Void in
    DispatchQueue.main.async(execute: {

        print("bytes sent \(bytesSent), total bytes sent \(totalBytesSent), of total \(totalBytesExpectedToSend)")

    })
}


transferManager?.upload(uploadRequest).continue(with: AWSExecutor.mainThread(), withSuccessBlock: { (taskk: AWSTask) -> Any? in
    if taskk.error != nil {
        // Error.
    } else {
        // Do something with your result.
    }
    return nil
})
}

I know I don't need to apply it to image, but this is just an example, by default I'm going to send files like 100mb.

When I put my phone into airplane mode during the transfer then turn the network on again, it does not finish the upload task.

Docs are not saying explicitly what should I do to resume interrupted task.

Here is what I tried:

I put initialization of request and manager into viewDidLoad() to assure I'm not creating another request

class ViewController: UIViewController {

var uploadRequest:AWSS3TransferManagerUploadRequest!
var transferManager: AWSS3TransferManager!


override func viewDidLoad() {
    super.viewDidLoad()
    uploadRequest = AWSS3TransferManagerUploadRequest()
    transferManager = AWSS3TransferManager.default()

}

and tried to call

    func resumeTransfer() {

   transferManager?.resumeAll(nil)

}

But it does not work.

Thanks in advance

Upvotes: 2

Views: 2163

Answers (1)

theDC
theDC

Reputation: 6484

It turns out that Transfer Utility is the right tool to accomplish this task

func uploadData(data: NSData) {

    let expression = AWSS3TransferUtilityUploadExpression()
    expression.progressBlock = progressBlock

    let transferUtility = AWSS3TransferUtility.default()

    transferUtility.uploadData(
        data as Data,
        bucket: "test",
        key: "test/test.jpeg",
        contentType: "image/jpeg",
        expression: expression,
        completionHander: completionHandler).continue(successBlock: { (task) -> AnyObject! in
            if let error = task.error {
                NSLog("Error: %@",error.localizedDescription);

            }
            if let exception = task.exception {
                NSLog("Exception: %@",exception.description);

            }
            if let _ = task.result {

                NSLog("Upload Starting!")
                // Do something with uploadTask.
            }

            return nil;
        })
}

This way all upload stuff happens in the background, I don't have to worry about app being killed by the iOS, about networks problem etc.

One can even specify

configuration?.allowsCellularAccess = false

in AWSServiceConfiguration

to resume the task only when wifi is available.

Upvotes: 3

Related Questions