3

I'd like to show users a progress bar when uploading video files recorded within an iOS app to Firebase, so I'm using the observeStatus feature of the SDK:

// Create a root reference
FIRStorageReference *storageRef = [_storage reference];

// Create a reference to the video
FIRStorageReference *videoRef = [storageRef child:uuidString];

// Upload the file
FIRStorageUploadTask* uploadTask = [videoRef putFile:url metadata:nil];

[uploadTask observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot *snapshot) {
    // A progress event occurred
    double percentComplete = 100.0 * (snapshot.progress.completedUnitCount) / (snapshot.progress.totalUnitCount);

    NSLog(@"Video with ID %d recording upload progress: %f, completed unit count %lld, total unit count %lld", video.videoId, percentComplete, snapshot.progress.completedUnitCount, snapshot.progress.totalUnitCount);
}];

However, 'Total Unit Count' always seems to be 0, meaning the calculated percent complete goes a bit bonkers with the whole divide-by-0 situation:

Video with ID 3 recording upload progress: inf, completed unit count 163922, total unit count 0

Am I doing something wrong? Following the docs as described here.

[Replicated also in Swift]

Mike McDonald
  • 15,609
  • 2
  • 46
  • 49
Paul
  • 753
  • 5
  • 19

3 Answers3

1

EDITED

Using data upload is working fine:

    NSData *data = // ... some real data to upload

    FIRStorageReference *storageRef = [storage referenceForURL:@"gs://<YOURPATH>"];

    // Upload the file to the path
    FIRStorageUploadTask *uploadTask = [storageRef putData:data metadata:nil completion:^(FIRStorageMetadata * _Nullable metadata, NSError * _Nullable error) {

        if (error != nil) {
            // Error handle it
        } else {
            NSString *urlToDownload = metadata.downloadURL;
        }

    }];

    // Add a progress observer to an upload task
    [uploadTask observeStatus:FIRStorageTaskStatusProgress
                          handler:^(FIRStorageTaskSnapshot *snapshot) {
                              // A progress event occurred
                              double percentComplete = 100.0 * (snapshot.progress.completedUnitCount) / (snapshot.progress.totalUnitCount);
                              NSLog(@"\n\nloading...%f",percentComplete);
                          }];

I hope this can help either OP or anyone else.

J. Lopes
  • 1,336
  • 16
  • 27
  • I can certainly give it a go, but thinking it might not resolve the issue as the "completed unit count" figure increases as expected during the upload in the log trace. – Paul Jun 03 '16 at 08:26
  • 1
    Yep, unfortunately this is the correct behavior: data has a length property which we can grab the "file size" off, while URLs don't have a similar mechanism (you have to dive through a few layers: http://stackoverflow.com/questions/5743856/finding-files-size). Will fix this soon. – Mike McDonald Jun 14 '16 at 17:14
1

This is not the answer either of us want but I am guessing there's a bug in the Firebase SDK where it's not creating the NSProgress instance correctly.

So, as a work around you can capture the file size before you create the upload task. I am using this extension (which is super crashy with the IUOs for convenience sake).

extension NSFileManager {
    func fileSize(atUrl url: NSURL) -> Int64 {
        return try! NSFileManager.defaultManager().attributesOfItemAtPath(url.path!)[NSFileSize]!.longLongValue
    }
}

Capture the file size value and use that in place of totalUnitCount in your calculation.

FWIW I filed a bug for this issue at https://firebase.google.com/support/contact/bugs-features/

Chris Wagner
  • 20,773
  • 8
  • 74
  • 95
1

We actually create the NSProgress correctly, and update it appropriately for in memory uploads (putData), but aren't getting the file size for file uploads (putFile) since apparently I didn't discover file attributes/they weren't always correct.

I'm working on a fix shortly, for now you can use the NSFileManager.defaultManager().attributesOfItemAtPath(url.path!)[NSFileSize]!.longLongValue workaround to get the file size :)

EDIT (10/10/16): this has been resolved, and if you use the latest version of Firebase Storage, you won't have this problem :)

Mike McDonald
  • 15,609
  • 2
  • 46
  • 49