FileSystem.createDownloadResumable Callback - Help

Hi all.

I’ve spent the last couple of days trying to figure out a solution to this, and I’m really struggling to come up with anything.

Basically, in my app, I have a downloadSong Redux action creator that gets a link from an external API and downloads a file from it. The files download just fine, but the callback that provides download progress data is behaving strangely.

The first run goes as expected - the file downloads correctly, and the callback gets called until download completion, correctly updating download progress along the way.

For any subsequent downloads, the callback is called until the new download ends, but callbacks for previous (completed) downloads are also called simultaneously.

The callbacks from previous downloads contain new totalBytesWritten / totalBytesExpectedToWrite values, but the _id value is the same as when the callback was originally passed to createDownloadResumable.

Ultimately the reducer receives the following actions from the callbacks, and I really don’t understand why the callback is firing for old downloads as well as current.

{
    type: UPDATE_DOWNLOAD_PROGRESS,
    payload: {
      songId: VALUE FROM PREVIOUSLY COMPLETED DOWNLOAD,
      totalBytesWritten: VALUE FROM NEW DOWNLOAD,
      totalBytesExpectedToWrite: VALUE FROM NEW DOWNLOAD
    }
}
{
    type: UPDATE_DOWNLOAD_PROGRESS,
    payload: {
      songId: VALUE FROM NEW DOWNLOAD,
      totalBytesWritten: VALUE FROM NEW DOWNLOAD,
      totalBytesExpectedToWrite: VALUE FROM NEW DOWNLOAD
    }
}

The same thing also happens with simultaneous downloads. The callback for the older downloads starts getting called with totalBytesWritten / totalBytesExpectedToWrite for the newest download. Again, why?

All I want is the callbacks to fire independently of other downloads. The file themselves actually download properly and independently from each other, so I don’t understand why the callbacks are different.

If anyone has any ideas, solutions, or tips regarding this, I would be eternally grateful!

The appropriate code can be seen below.

export const downloadSong = song => async dispatch => {
  const { youTubeUrl, _id } = song;
  dispatch(downloadSongStart(_id));

    let { data } = await axios.get(`http://www.youtubeinmp3.com/fetch/?format=json&video=${youTubeUrl}`);
    let { link } = data;

    const callback = ({ totalBytesWritten, totalBytesExpectedToWrite }) => dispatch(updateDownloadProgress(
      _id,
      totalBytesWritten,
      totalBytesExpectedToWrite
    ));

    const downloadResumable = FileSystem.createDownloadResumable(
      link,
      FileSystem.documentDirectory + `${_id}.mp3`,
      {},
      callback
    );

    const { uri } = await downloadResumable.downloadAsync();
    console.log('Finished downloading to ', uri);

    const updatedSong = { ...song, localUri: uri, downloadedOn: Date.now() };
    return dispatch(downloadSongSuccess(updatedSong));

  } catch (err) {
    console.log(err);
    dispatch(downloadSongFailure(song, err));
  }
};


const updateDownloadProgress = (songId, totalBytesWritten, totalBytesExpectedToWrite) => {
  return {
    type: UPDATE_DOWNLOAD_PROGRESS,
    payload: {
      songId,
      totalBytesWritten,
      totalBytesExpectedToWrite,
    }
  };
};

Hello,

We found this bug as well. The callback is being fired without any regard to the id of the download. The fix will be included in the next release which is about 2 weeks away.

That’s great news! I’ll keep my eyes peeled.

Hi, I’m having some strange behaviour too. I’m downloading multiple files in sequence (not in parallel) to avoid overloading the server (does this make sense?).
Here’s some code:

    const sacarTotal = async (canciones) => {
      await canciones.map((cancion) => { totalSize += cancion.size; });
    }
    sacarTotal(canciones);
    console.log('Total Size: ', totalSize);

    const callback = downloadProgress => {
      totalDescargado += downloadProgress.totalBytesWritten;
      const progress = totalDescargado / totalSize;
      this.setState({
        downloadProgress: (progress * 100).toFixed(2),
        bytesToDownload: (totalSize / 1024 / 1024).toFixed(2),
        downloadedBytes: (totalDescargado / 1024 / 1024).toFixed(2),
      });
    };

So, totalDescargado is where I store the total downloaded bytes for all files. totalSize I got it from a value of a JSON file which indicates what to download, I did the sum with a calculator just to check sacarTotal function is returning the correct value.
I want to show a total progress for all the downloads, but instead I get (always a different) enormous number in my totalDescargado so my percentage goes to 8000% or so.

Am I doing something wrong? or is it the callback being called so that it sums up all the time?

Bump, any news on this?