Internal and external storage in react native
Tags: reactnative, file, storage, opensource
Published: 2022-08-30 20:39:18

I have been working with react native at work for 3 years, but I haven't touched the file system.

Recently I built an app called [PreCloud: Encrypt before upload](https://www.peng.kiwi/precloud), with which you can encrypt texts and files, then you can upload the encrypted texts and files to wherever you want, making any cloud provider an encrypted storage. It's free and [open source](https://github.com/penghuili/PreCloud). Give it a try :)

In this post I will share about managing files with react native.

---

## Libraries used

- [react-native-document-picker](https://github.com/rnmods/react-native-document-picker): Pick files from phone;
- [react-native-fs](https://github.com/itinance/react-native-fs): Manage files in the internal storage of your app, more on this later;
- [react-native-share](https://github.com/react-native-share/react-native-share): Share files to other apps;
- [react-native-file-viewer](https://github.com/vinzscam/react-native-file-viewer): View file in your app;

---

## Two kinds of storage

### 1. Intertal storage

Every app has its own storage, that other apps don't have access to. For example this is the `Cache` folder of my app in Simulator:
```
/Users/penghui/Library/Developer/CoreSimulator/Devices/5BAEC586-2BA0-42A0-B615-926F1A4D59A0/data/Containers/Data/Application/EBB8401E-3B16-4A3E-98A1-D2DDC3900A90/Library/Caches
```
And this is the `Documents` folder:
```
/Users/penghui/Library/Developer/CoreSimulator/Devices/5BAEC586-2BA0-42A0-B615-926F1A4D59A0/data/Containers/Data/Application/EBB8401E-3B16-4A3E-98A1-D2DDC3900A90/Documents
```
There are other folders, but I am only instersted in these 2 for now. You can check the full list in the [react-native-fs](https://github.com/itinance/react-native-fs#constants) doc, with more explanation.

I think these are the places where Spotify saves your downloaded music and where Youtube saves your downloaded videos.

[react-native-fs](https://github.com/itinance/react-native-fs) is the perfect tool to handle files in internal storage, you can check their doc to find the functions you need.

But like mentioned before, files in the internal storage can't be viewed by your phones `Files` app or `Photos` app, and you also can't just read files from external storage.


### 2. External storage
This is the normal storage you see on your phone, it's what you see in the `Files` app, both for iOS and Android.

---

## Moving files around

### 1. From external to internal

[react-native-fs](https://github.com/itinance/react-native-fs) is (**almost**) only for processing internal files. So before it can do something with the file, you need to move it from external storage.

For this we need [react-native-document-picker](https://github.com/rnmods/react-native-document-picker).

We need the [pick](https://github.com/rnmods/react-native-document-picker) function, which will open the file picker. We can specify the [copyTo](https://github.com/rnmods/react-native-document-picker#ios-and-android-only-copytocachesdirectory--documentdirectory) param, it supports 2 values: `cachesDirectory` and `documentDirectory`, what it does is, after users pick a file / multiple files in the file picker, the picked file/files will be copied to the `Caches` or `Documents` folder of your app's internal storage. Ta-da.

**Note:** [react-native-document-picker](https://github.com/rnmods/react-native-document-picker) can pick all external files on Android (your images, files etc.), but on iOS, it can only pick files in the `Files` app, it can't pick images in the `Photos` app. You need to firstly "share" an image with the "Save to Files" option, then the image will be moved to `Files`, then you can pick it with react-native-document-picker.

If you need to pick images, there are some other libraries, I haven't tried them, but should be straightforward.

### 2. From internal to external

The file is moved to the internal storage, and you did some fancy processing (For me, I encrypt the file, see some code [here](https://github.com/penghuili/PreCloud/blob/how-to-files/nodejs-assets/nodejs-project/main.js)), then you want to move the processed file to external storage.

#### Android
On Android, it's easy, [react-native-fs](https://github.com/itinance/react-native-fs) can do the job (remember the "almost" in "react-native-fs is almost only for processing internal files"?) It has a [DownloadDirectoryPath](https://github.com/itinance/react-native-fs#constants), which is only available on Android.

You can use the [copyFile](https://github.com/itinance/react-native-fs#copyfilefilepath-string-destpath-string-promisevoid) function:
```
  await RNFS.copyFile(internalFilePath, `RNFS.DownloadDirectoryPath/${fileName}`);
```

Then the file will be copied to the `Download` folder of the external storage. Done.

You can see some real code [here](https://github.com/penghuili/PreCloud/blob/how-to-files/src/components/FileItem.js#L41).

#### iOS
But on iOS, I haven't found an easy way to move a file like that.

I ended up using [react-native-share](https://github.com/react-native-share/react-native-share). It will open a share files bottom toolbox, then you can choose the "Save to Files" options to download it to the `Files` app.

react-native-share also works on Android of course.

And I mis-used the [saveToFiles](https://react-native-share.github.io/react-native-share/docs/share-open#supported-options) option :) The flag is only available for iOS. If it's false, and for example you are sharing an image, the opened share toolbox will have other options, like add the image to an album; But when `saveToFiles` is true, the toolbox will only show the "Save to Files" option.

So in my app, I have 2 icons under a file, one download icon, for which I set the `saveToFiles` flag to true, and one share icon, for which I set the `saveToFiles` flag to false.

There is actually another way I found in [this answer](https://stackoverflow.com/a/56356490/5508710), which is you set the `UISupportsDocumentBrowser` flag in the `Info.plist` to true, and you use react-native-fs to save files to the `Documents` folder of the internal storage, then the files will be accessible by the `Files` app, that's it!
I tried it, it works, but I don't like it, I feel I have less control.

If you know a better way to download files on iOS, please let me know!

---

## Bonus: view internal files in your app
You can use the [react-native-file-viewer](https://github.com/vinzscam/react-native-file-viewer) lib to open internal files, like an image, a PDF file etc. It's very easy to use, have a try.

---

You can check all my app's code in [github](https://github.com/penghuili/PreCloud/tree/master);

And if you are interested, try my [PreCloud](https://www.peng.kiwi/precloud) app, to protect your privacy.
Play store: https://play.google.com/store/apps/details?id=com.precloud
App store: https://apps.apple.com/us/app/precloud/id1638793841

Like I said in the beginning, it's free, open source, and has no tracking and no server.