circuit

Download Files in React Native with RNFetchBlob

A concise and easy-to-follow guide on downloading files in React Native apps.




Photo by Christin Hume on Unsplash

Photo by Christin Hume on Unsplash

In a previous article, I showed you how to add the library to your project and how to use it for uploading files to a remote server. The steps for adding the library to your project can also be found there. (TLDR; yarn add rn-fetch-blob).

Now, there's some additional configuration that needs to be done in order to download files with RNFetchBlob.

Since we are going to use Android Download Manager, we have to add the following intent filter to AndroidManifest.xml (app):

<intent-filter>
  <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>

If you also plan on restricting the download to wifi, then you'll also need the following permission in the manifest file:

<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE" />

Let's look at the code:

I'm going to break it down now.

Depending on the current platform, the file will be downloaded to DownloadDir on Android, and to DocumentDir on iOS. We're using a selector to pick the correct one.

In the snippet, GenericFile is nothing but an interface that has some basic info about the file (name, extension, nothing much). You need to know the extension in order to correctly store the file on the device. Otherwise, you'll run into a nightmare where the phone downloads .pdf and .png files which cannot be opened normally since they're viewed as binary files.

Based on the extension, we select the correct mimeType. I had omitted the mime field initially in the config. Oh man, how much useless debugging for such a little thing.

One small note on the manner in which the mimeType has been determined in the snippet: it's more of a proof of concept way. In a real-world app, you might want to refactor that. I'd extract to a utils file 3 methods, each one returning a boolean: isImage, isPdfFile, and isVideoFile. Maybe you also want to support audio files. The world is yours! However, you should probably export some lists containing your supported types and check whether or not the extension of the file is contained within the appropriate list.

A must-do that will ensure a good user experience is to set useDownloadManager to true on the Android side (line 46) and combine it with the notification flag set to true. By doing so, the user will see the downloaded file in the notifications panel.

DownloadManager will properly take care of the file download on Android devices in the background, taking into consideration special cases such as rebooting the device or losing your internet connection. Therefore, by using this system service, you ensure that the user will indeed end up successfully downloading the file that they requested through your app.

Downloads on iOS work a bit differently. As you see, if the platform is iOS, we call

RNFetchBlob.ios.openDocument(resp.data);

In order to open the downloaded PDF, image, or video and offer the user a preview and the possibility to download the file to their device or to simply view it.

One small tip when downloading files on iOS: if the file download (file preview, in this case) action is initiated from a bottom-sheet dialog, make sure that you close the dialog before initiating the preview operation. I can tell you from experience that the preview will not work unless you do so.

After correctly configuring RNFetchBlob, fetching the file itself is a piece of cake. As you see, the download itself happens in the following code segment:

RNFetchBlob.config(configOptions as RNFetchBlobConfig)
  .fetch('GET', downloadUrl)
  .then((resp) => {
    console.log(resp);
    signalSuccess();
    if (isIOS) {
        RNFetchBlob.ios.openDocument(resp.data);
    }
  })
  .catch((e) => {
    // your error handling approach
  });

Your error handling might simply be a snackbar that informs the user about the unfortunate event. In the same manner, you might also want to display a snackbar in the case when the download has indeed been successful (who doesn't love good news in their apps?)

Conclusion

That's it for now. Thanks a lot for reading and I hope that this has been helpful for you!




Continue Learning