itinance / react-native-fs

Native filesystem access for react-native
MIT License
4.92k stars 964 forks source link

Android download with downloadUrl takes minutes (20Mb) or 3s on iOS without timeout error #741

Open philipigov opened 4 years ago

philipigov commented 4 years ago

running react-native 0.59.8 and react-native-fs and 2.13.3

The download file sizes are from 5Mb to 20Mb and on iOS with 32 files are downloading in one to two minutes. On Android, they are taking between 10 minutes and 45 minutes with some individual files taking between 90s to 390s or sometimes between 3 to 7 seconds. It does seem as if the file will take a long time if it does not download within about 10 seconds. I am not seeing timeout errors. The code below has been edited slightly for brevity and security. There are about 30 files in total so over 150Mb.


import { Platform } from 'react-native';
import firebase from 'react-native-firebase';
import fs from 'react-native-fs';

const BASE_DIR = firebase.storage.Native.DOCUMENT_DIRECTORY_PATH;

const downloadFile = async (filename: string, downloadUrl: string) => {
  const result = fs.downloadFile({
    background: true,
    fromUrl: downloadUrl,
    toFile: `${BASE_DIR}/${filename}`,
  });

  await result.promise;

  if (Platform.OS === 'ios') {
    // Background Support: Mark the file as completed on iOS
    await fs.completeHandlerIOS(result.jobId);
  }
};

export const download = () => async (dispatch: any => void) => {
  dispatch(downloadStart());
  var user
  var logname
  var filenames = {"filename1.mp3":"https://firebasestorage.googleapis.com/v0/b/random.appspot.com/o/myfiles%2Ffilename1.mp3?alt=media&token=6c1eca",
"filename2.mp3":"https://firebasestorage.googleapis.com/v0/b/random.appspot.com/o/myfiles%2Ffilename2.mp3?alt=media&token=1f4192",
"filename3.mp3":"https://firebasestorage.googleapis.com/v0/b/random.appspot.com/o/myfiles%2Ffilename3.mp3?alt=media&token=336a85",
}

  if (global.myuser == null) {
    user = firebase.auth().currentUser;

    if (user) {
      global.myuser = user.uid
    }
    else {
      global.myuser = "not known"
    }
  }

  try {

    var totalFiles = filenames.length

    for (let i = 0; i < totalFiles; i++) {
      const filename = filenames[i];
      logname = filename + "-" + i + "-begin"
      const downloadUrl = filenames[filename];
      // eslint-disable-next-line no-await-in-loop

      await firebase
      .firestore()
      .collection(`logging`)
      .doc(global.myuser)
      .collection('files')
      .add({ logname, 'filenumber': i, totalFiles, 'timestamp': firebase.firestore.FieldValue.serverTimestamp(),});

      await downloadFile(filename, downloadUrl);

      logname = filename + "-" + i + "-end"
      await firebase
      .firestore()
      .collection(`logging`)
      .doc(global.myuser)
      .collection('files')
      .add({ logname, 'filenumber': i, totalFiles, 'timestamp': firebase.firestore.FieldValue.serverTimestamp(),});

    }

    dispatch(downloadSuccess());
  } catch (err) {
    dispatch(downloadError(err));
  }
};

`import { Platform } from 'react-native';
import firebase from 'react-native-firebase';
import fs from 'react-native-fs';

const BASE_DIR = firebase.storage.Native.DOCUMENT_DIRECTORY_PATH;

const downloadFile = async (filename: string, downloadUrl: string) => {
  const result = fs.downloadFile({
    background: true,
    fromUrl: downloadUrl,
    toFile: `${BASE_DIR}/${filename}`,
  });

  await result.promise;

  if (Platform.OS === 'ios') {
    // Background Support: Mark the file as completed on iOS
    await fs.completeHandlerIOS(result.jobId);
  }
};

export const download = () => async (dispatch: any => void) => {
  dispatch(downloadStart());
  var user
  var logname
  var filenames = {"filename1.mp3":"https://firebasestorage.googleapis.com/v0/b/random.appspot.com/o/myfiles%2Ffilename1.mp3?alt=media&token=6c1eca",
"filename2.mp3":"https://firebasestorage.googleapis.com/v0/b/random.appspot.com/o/myfiles%2Ffilename2.mp3?alt=media&token=1f4192",
"filename3.mp3":"https://firebasestorage.googleapis.com/v0/b/random.appspot.com/o/myfiles%2Ffilename3.mp3?alt=media&token=336a85",
}

  if (global.myuser == null) {
    user = firebase.auth().currentUser;

    if (user) {
      global.myuser = user.uid
    }
    else {
      global.myuser = "not known"
    }
  }

  try {

    var totalFiles = filenames.length

    for (let i = 0; i < totalFiles; i++) {
      const filename = filenames[i];
      logname = filename + "-" + i + "-begin"
      const downloadUrl = filenames[filename];
      // eslint-disable-next-line no-await-in-loop

      await firebase
      .firestore()
      .collection(`logging`)
      .doc(global.myuser)
      .collection('files')
      .add({ logname, 'filenumber': i, totalFiles, 'timestamp': firebase.firestore.FieldValue.serverTimestamp(),});

      await downloadFile(filename, downloadUrl);

      logname = filename + "-" + i + "-end"
      await firebase
      .firestore()
      .collection(`logging`)
      .doc(global.myuser)
      .collection('files')
      .add({ logname, 'filenumber': i, totalFiles, 'timestamp': firebase.firestore.FieldValue.serverTimestamp(),});

    }

    dispatch(downloadSuccess());
  } catch (err) {
    dispatch(downloadError(err));
  }
};`

I have tried doing all files at the same time instead of individually and that did give some timeout errors. 

The same problem has shown up on phones running Android 6.0 to 9.0. 

The same code takes about 2 minutes on iOS running in the same area and using similar cellular data signal levels and WiFi

Using the firebase SDK to do a storage download of the same files (not using downloadUrls) also takes about 2 minutes on Android.

I have tried changing the readTimeout and networkTimeout to 20000 but all this seemed to do was make the minimum time a file would download to 20 seconds.

If there is anything else I can provide, let me know. 

I have monitored the storage used by the app as it is running and it does appear as if the download pauses for long periods as the data stored does not increase for a considerable amount of time.
arunim2405 commented 3 years ago

Did you find a fix for this? I am in a similar situation

hoanghuy0604 commented 1 year ago

Please help, I can't catching error when lost network connection on IOS