Progress Bar for Firebase upload


#1

In my app, I’m uploading significantly large videos to Firebase and would like to show a progress bar with % of the overall progress. I know how to make a component that looks like a progress bar, but I don’t know how to link it to the progress of Firebase upload. Any advice will be highly appreciated!


#2

Check this out.


#3

I got the answer in theory, it’s this from here (https://firebase.google.com/docs/reference/js/firebase.storage.UploadTaskSnapshot)

firebase.storage.UploadTaskSnapshot.bytesTransferred
and
irebase.storage.UploadTaskSnapshot.totalBytes

But I get this error for the following:

Property UploadTaskSnapshot doesn't exist on type 'typeof storage'

Any ideas what I’m doing wrong?
Thanks!!


#4

Ok, I almost got this working, still two issues:

Events don’t come that often, so when you upload a huge file (15Mb), the progress jumps in 10-15% steps, not very gradually. Any way to make the.on('state_changed' be called more often?


#5

This is my favorite thread in quite a while, because the questions sound so simple, but they are actually hard!

Sounds as though you probably know the answer to this already, but I’ll share what I discovered. Firebase manually creates their typings file, and they don’t update typings as often as they update the SDK, so typings is always behind. The most up-to-date typings comes with the firebase installation – there’s no magic fix on github anywhere. Their official suggestion in gitHub threads is to recast to “as any” to get around this problem. So

(firebase.storage as any).UploadTaskSnapshot

et cetera. I haven’t figured out how to get more frequent event updates yet. One thing I’ve considered, but haven’t tried, is to create an interval Observable that fires every 0.1 seconds, and each time it fires, I request a snapshot. Not sure if I’ll get to testing that tonight or not, so I figured I’d mention it as a possible strategy. If you figure it out, please let me know.


#6

Here’s my progress so far. I’m using setTimeout() to run my method as often as needed:

  function printSome() {
      if(count < 10) {
        count++;
        console.log(count);
        setTimeout(printSome, 500);
      }
    }
    printSome();

My problem is that I can’t get firebase.storage.UploadTaskSnapshot.bytesTransferred directly from firebasePutString, but need to use the .on("state_changed") method, but this method is called only every few seconds, so the progress bar isn’t really dynamic. I can’t figure out how to call it directly from my firebasePutString object. Any ideas??

let firebasePutString = firebase.storage().ref(`/${UID}/${fileName}`).putString(data, 'data_url');
firebasePutString.on('state_changed',
function progress(snapshot) {
  console.log("snapshot: " + snapshot);
  this.percentage = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
  console.log("percentage2: " + this.percentage);
},
function error(err) {},
function complete() {});

#7

This seems to work, at least in the console.

uploadVideo(videoFile: File) {
    const videoRef = firebase.storage().ref(yourFilePath);
    const task = videoRef.put(videoFile);
    Observable.interval(100).subscribe( _ => console.log(task.snapshot.bytesTransferred));
  }

Forgot to mention: Might still need the “on” listener to detect completion, so you can unsubscribe from the interval Observable when you’re done with the upload.


#8

Thanks so much, it works!
The only problem remains with Google, they update the snapshot every 256Kb, so basically the progress bar won’t be that dynamic on files of a few Mb. I’m now thinking of a clever hack to just use setTimeout() method and do a smooth but “untrue” progress bar tied to the duration of the video clip. I know it’s not ideal, but don’t see anything better… Any suggestions?

Thanks again!!!


#9

Maybe have variables currentPercentage:number and taskBarActive: boolean, and when the task bar is active currentPercentage ticks up by 0.01 at each time interval until it reaches the current progress, which has a maximum of 1.0 and equals bytesTransferred / totalBytesToTransfer. Smooths it out a bit.


#10

Excellent idea! Done! And it looks almost perfectly smooth!!
Thanks for your help and advice!


#11

Добрый день. Внутри функции “progress(snapshot)” вы присваиваете значение переменной this.percentage. И это у вас работает? У меня не получается изменить свойство класса из функции обратного вызова в uploadTask. И не я один в интернете не могу так сделать. Там теряется контекст…

Hi! I see you use assignment to class property inside callback function (marked code line). Is it works for you? When I try to do such assignment the percentage property of class stays unmodified. Because context is changed…


#12

Нашёл решение. Нужно присвоить объект this другой переменной перед использованием uploadTask.on(). Затем, внутри callback-функции, через эту переменную будет доступен внешний this.

Сообщение на Stackoverflow.