react-native-fs icon indicating copy to clipboard operation
react-native-fs copied to clipboard

RNFS.downloadFile resolves without bytesWritten very often (RNFS v1.5.1)

Open tomprogers opened this issue 8 years ago • 13 comments

react-native v0.33.0 react-native-fs v1.5.1

I make a habit of checking the size-on-disk of each file I download, because I've noticed that sometimes a download operation will produce a truncated file (less than 200 bytes, for a file in Amazon S3 that's 90k).

Lately, I've started relying on the resolution value of RNFS.downloadFile, which is documented as containing jobId, bytesWritten, and statusCode. Today I've discovered that bytesWritten is often undefined, even though the file downloaded correctly and the statusCode is 200.

I used RNFS.stat to verify the result of RNFS.downloadFile. Even though bytesWritten is undefined, stat reports a size of 70k on disk (the correct size).

By "very often," I mean that bytesWritten is incorrect 74 times out of 75. I've been building a caching module, and while putting it through its paces I've done nearly 1000 downloads of files around 90k.

Apologies if this is fixed in the newest version of RNFS.

tomprogers avatar Sep 23 '16 00:09 tomprogers

@tomprogers were yo able to look into this issue further and come to a conclusion where we might have a bug?

johanneslumpe avatar Oct 14 '16 12:10 johanneslumpe

@johanneslumpe Sorry, but no. I'm not an Obj-C dev. I can't trace or debug execution once it leaves the JS world. I see some code in Downloader.m that appears relevant, but I'm not equipped to figure out why it's not working.

tomprogers avatar Oct 14 '16 16:10 tomprogers

i'm experiencing this too, byteswritten is undefined like 1 in 5

br4nnigan avatar Jan 18 '17 12:01 br4nnigan

For what it's worth, I am getting this issue as well. But I seem to be getting it 100% for specific files.

I have been testing with some mp4 files and one jpeg file, and it consistently returns undefined for bytesWritten for the jpeg file, but returns correct information for the mp4 files.

Maybe it has something to do with small files? E.g. there is some kind of race that causes bytesWritten to appear undefined if the file is really small and the download completes too quickly? (random thoughts)

dojiboy9 avatar Jan 19 '17 08:01 dojiboy9

I get this about once in 20 times. It is definitely happening for small files under 100KB in my case.

anshul-kai avatar Apr 13 '17 22:04 anshul-kai

Also getting this error.

Is it okey to assume that if the DownloadResult promise resolves then the file has been correctly downloaded? So instead of checking if bytesWritten is equal to downloaded file size I do something like:

    const downloadInfo = await fileManager.downloadFile({
      fromUrl: asset.url,
      toFile: `${AssetsManager.ASSETS_BASE_PATH}${asset.version}/${asset.name}`,
      headers: getOpts.headers,
    })

    if (await downloadInfo.promise) {
      // ASSET HAS BEEN DOWNLOADED!
    }

I have tested this by removing internet connection and it worked (promise didn't resolve successfully). Am I missing a case where this may fail?

aschenkel avatar Oct 19 '17 14:10 aschenkel

I have not tested this with the recent updates but I have had the promise resolve incorrectly. Below is a snippet of what works for me. I wrap the entire download call into a promise and resolve it only if the checks below pass.

// bytesWritten comes back undefined at times
// https://github.com/johanneslumpe/react-native-fs/issues/181
if (statusCode === 200 && (!bytesWritten || bytesWritten === contentLength)) {
  // Success
}

anshul-kai avatar Oct 19 '17 16:10 anshul-kai

It's still a fact that bad bytesWritten is a bug that ought to be fixed.

Yes, the promise resolves IFF the download completes, but without bytesWritten, it's impossible to know whether the data you saved to disk is the data you expected. Common example: make an incorrect "download" request to a URL that responds with an error page. Naive download code will unwittingly save the error HTML as a file on the device. The workaround is to make a second FS call to get the size of the new file from disk, but that's additional complexity that this module is supposed to eliminate.

Fix this bug.

tomprogers avatar Oct 19 '17 17:10 tomprogers

I'm now seeing some very strange behavior with bytesWritten all over the place ie. sometimes larger than contentLength, sometimes smaller and obviously undefined at times.

anshul-kai avatar Apr 25 '20 15:04 anshul-kai

I am facing this issue in iOS ....same code works fine on Android I am using react-native version 0.63 react-native-fs version is 2.18.0 This is the response I am getting for iOS {"bytesWritten": 0, "jobId": 12, "statusCode": 200}

But there is not file written to the path I have given in toFile argument My download url is a .png image from web

MuhammadAbdullah54321 avatar May 29 '22 07:05 MuhammadAbdullah54321

I am facing this issue in iOS ....same code works fine on Android I am using react-native version 0.63 react-native-fs version is 2.18.0 This is the response I am getting for iOS {"bytesWritten": 0, "jobId": 12, "statusCode": 200}

But there is not file written to the path I have given in toFile argument My download url is a .png image from web

Ok so I found out that issue in my case was that I was not saving image in default DocumentDirectoryPath rather I was trying to save image in a folder one step deep in DocumentDirectoryPath but that folder was never created

So I was giving ${RNFS.DocumentDirectoryPath}/MyAppName/products/image123.png to toFile parameter when in fact there was no folder name products

MuhammadAbdullah54321 avatar May 29 '22 08:05 MuhammadAbdullah54321

I am facing this issue in iOS ....same code works fine on Android I am using react-native version 0.63 react-native-fs version is 2.18.0 This is the response I am getting for iOS {"bytesWritten": 0, "jobId": 12, "statusCode": 200} But there is not file written to the path I have given in toFile argument My download url is a .png image from web

Ok so I found out that issue in my case was that I was not saving image in default DocumentDirectoryPath rather I was trying to save image in a folder one step deep in DocumentDirectoryPath but that folder was never created

So I was giving ${RNFS.DocumentDirectoryPath}/MyAppName/products/image123.png to toFile parameter when in fact there was no folder name products. that's why I first had to create folder products inside RNFS.DocumentDirectoryPath}/MyAppName/ and then it worked fine

MuhammadAbdullah54321 avatar May 29 '22 08:05 MuhammadAbdullah54321