Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase Storage Upload Fails in Adverse Network Conditions iOS

Firebase Storage claims here in its iOS documentation that it

performs uploads and downloads regardless of network quality. Uploads and downloads are robust, meaning they restart where they stopped

so one would expect it to handle a loss of connection when uploading, but it doesn't seem to.

With the following Swift code in iOS, I am able to perform an upload just fine when there is a connection, but if the device doesn't have a connection or if it is ever disconnected from the network it goes to the failure condition.

let storage = FIRStorage.storage().referenceForURL("VALID_URL_REMOVED")

let imagesRef = storage.child("images/test.jpg")

let data = UIImageJPEGRepresentation(observationImage!, 0.7);

let uploadTask = imagesRef.putData(data!, metadata: nil)

uploadTask.observeStatus(.Progress) { snapshot in
    // Upload reported progress
    if let progress = snapshot.progress {
        let percentComplete = 100.0 * Double(progress.completedUnitCount) / Double(progress.totalUnitCount)
        print("percent \(percentComplete)")
    }
}

uploadTask.observeStatus(.Success) { snapshot in
    // Upload completed successfully
    print("success")
}

uploadTask.observeStatus(.Failure) { snapshot in
    print("error")
    print(snapshot.error?.localizedDescription)
}

The debug output for this code is as follows.

/*
percent 0.0
percent 0.0044084949781492
2016-06-30 11:49:16.480 Removed[5020:] <FIRAnalytics/DEBUG> Network status has changed. Code, status: 1, Disconnected
percent 0.0044084949781492
error
Optional("An unknown error occurred, please check the server response.")
*/

Firebase's Real Time Database offline storage is also set up with the following code, but I'm unsure of whether this is related.

FIRDatabase.database().persistenceEnabled = true

I have also tried manually setting the timeout as mentioned in the answers to this question using the following lines, with no change.

let config = FIRStorage()
config.maxUploadRetryTime = 1000000

Is there a way to have it handle these disconnects without implementing the functionality from scratch? Am I missing something?

like image 817
ThatGuyJames Avatar asked Jun 30 '16 16:06

ThatGuyJames


1 Answers

You are missing observers. Right now you only observe .success and .failure events. Try add observers for .resume, .pause, .progress to handle different events.

// Listen for state changes, errors, and completion of the upload.

uploadTask.observe(.resume) { snapshot in
// Upload resumed, also fires when the upload starts
}

uploadTask.observe(.pause) { snapshot in
// Upload paused
}

uploadTask.observe(.progress) { snapshot in
// Upload reported progress
let percentComplete = 100.0 * Double(snapshot.progress!.completedUnitCount)
/ Double(snapshot.progress!.totalUnitCount)

}

uploadTask.observe(.failure) { snapshot in
if let error = snapshot.error as? NSError {
switch (FIRStorageErrorCode(rawValue: error.code)!) {
case .objectNotFound:
  // File doesn't exist
  break
case .unauthorized:
  // User doesn't have permission to access file
  break
case .cancelled:
  // User canceled the upload
  break

/* ... */

case .unknown:
  // Unknown error occurred, inspect the server response
  break
default:
  // A separate error occurred. This is a good place to retry the upload.
  break
  }

 }

}
like image 185
whoswho Avatar answered Sep 22 '22 08:09

whoswho