File storage package?

What is the current preferred package for saving files from an Expo app (was build)?

I’ve come across

but don’t understand the relationship among them or whether one or more are falling out of fashion.

async-storage is a very simple key/value storage db
expo-file-system and react-native-fs allow you to interact with the filesystem (crud operations on files) and download/upload files. i personally prefer expo-file-system, but you can use whichever of these you like, both are good options.

1 Like

Hi @orome

Async Storage and things like SecureStore, MMKV and SQLite are databases. The first three are key/value stores, while SQLite is an embedded SQL database.

As Brent says, expo-file-system and react-native-fs are pretty much the same, but expo-file-system comes as part of the Expo SDK, so e.g. you can use it in Expo Go or in a Snack and it will work if you build with the Classic (expo build) build system. It looks to me like react-native-fs would require a config plugin and you’d get errors if you tried to use it in Expo Go or a Snack. You would have to build with the new EAS Build.

1 Like

@wodin @notbrent

A couple follow ups:

  1. Where can I find types? For example what is the type of the argument downloadProgress in the example from the docs:
    const callback = downloadProgress => {
        const progress = downloadProgress.totalBytesWritten / downloadProgress.totalBytesExpectedToWrite;
        // ...
    }
    
  2. Where are files being stored? Where should I look for FileSystem.documentDirectory? It’s not among the folders I see when I browse files on my device.

(Running using expo start --dev-client, which I suspect is part of the answer?)

  1. For keeping track of the progress, you need to pass in a callback as one of the arguments to the createDownloadResumable call. If you check the section of the docs that describes the args for createDownloadResumable it says what the argument to the callback looks like.

  2. It would be best to elaborate on what files you’re trying to save and for what purpose.

Storage on mobile devices is more complicated than on a PC. I haven’t needed to dig into it much before, so I don’t know all that much about the details, really, but I know a little about how it works on Android. I think iOS has some similarities to Android.

Basically, apps normally have access to some app-specific location to read/write files. There’s a “cache” location that the user can safely clear without losing app settings etc. and then there’s other storage that will get deleted when the user uninstalls the app.

If you want to write stuff to somewhere that other apps (e.g. a file manager app) can see then you need to write to some sort of external storage. If you’re working with images/videos then you might want to use Expo’s MediaLibrary API.

Android has something called the Storage Access Framework (and it’s usable from expo-file-system). I think it allows you access to things like the Downloads directory, but I’ve never used it.

Otherwise you might need some third party library in which case you’d need to build the app with EAS Build. e.g.:

Maybe this will help: android - Expo React Native, saving PDF files to Downloads folder - Stack Overflow

See the following post about the complexities of storage on Android (although I think it’s a bit out of date): The Storage Situation: External Storage
See also: Understanding Android Storage. Android storage is basically divided… | by Labhya Sharma | Medium

1 Like

@wodin Actually I think that the files are being sent where I expect them: in the Documents directory, which (normally) appears as a list of folders for each app in the Files app on iOS or browsing (a connected iOS device) in the macOS Finder. But, I think that in development mode, that location is hidden somewhere in a place created by Expo. I believe that if I ejected (is that the right word?) my app and ran it, I’d be able to see the files.

If you’re running the app in Expo Go then they would be stored somewhere under the Expo Go app’s storage.

I think the term you’re looking for is (used to be?) building a “standalone” app.

With the Classic build system, this means running expo build:ios.
With EAS Build, I think all three (default) options for building your app build essentially “standalone” apps. Although it’s a bit fuzzier with the development client, because technically that can run any number of apps as long as they rely on the same native code built into the dev client.

I’m afraid I have more experience with Android than iOS for a couple of reasons:

  • Android doesn’t prevent you from side-loading an app, so you don’t have to upload it to the Play Store in order to install it on your phone.
  • I have an Android phone and do not have an iPhone/iPad.

I do have a Macbook, though, so I can run the Simulator, but I don’t find that as convenient.

Fortunately, the Expo team has made it easier to test apps without having to upload them to the App Store/Testflight. To do this you can build an app with an Internal Distribution profile. The default EAS config sets up a profile called “preview” that builds the app like that. The only other speed bump is that as far as I understand it, Apple requires that any devices that are going to install the app have to be registered and somehow referenced in the distribution profile in order to be able to install these apps.

Anyway, if you want to create a standalone version of your app to test it, I believe you can either:

If you go with the first option and you’re happy with it, I think you can just promote it from Test Flight?
If you go with the EAS Build option, you would need to build with the “production” profile and submit that version to the App Store.

Note: If your app works in Expo Go, you can still use that for development, even if you’re using EAS Build to build preview/production versions of the app.

I hope the above has been coherent enough for you to get something useful out of it :slight_smile:

1 Like

@wodin All very helpful and coherent, thanks!

I’ll try preview (eventually) and see whether the files show up where I expect them. Right now I’m doing --profile development so perhaps that puts the files somewhere under storage managed by Expo (and thus not visible in the place I expect them)?

When you build with eas build --profile development I would expect it to act the same way as a production app in terms of where it stores its data. but I could be wrong.