This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
Expo FileSystem (legacy)
A library that provides access to the local file system on the device.
The
legacyversion of the FileSystem API is included in theexpo-file-systemlibrary. It can be used alongside the modern API for backward compatibility reasons.
expo-file-system provides access to a file system stored locally on the device. It is also capable of uploading and downloading files from network URLs.
How expo-file-system works differently inside of the Expo Go app
Within Expo Go, each project has a separate file system scope and has no access to the file system of other projects.
Installation
If you are installing this in an existing React Native app, make sure to install expo in your project.
Usage
Downloading files
Managing Giphy's
Server: handling multipart requests
The simple server in Node.js, which can save uploaded images to disk:
API
import * as FileSystem from 'expo-file-system/legacy';
Directories
The API takes file:// URIs pointing to local files on the device to identify files. Each app only has read and write access to locations under the following directories:
So, for example, the URI to a file named 'myFile' under 'myDirectory' in the app's user documents directory would be FileSystem.documentDirectory + 'myDirectory/myFile'.
Expo APIs that create files generally operate within these directories. This includes Audio recordings, Camera photos, ImagePicker results, SQLite databases and takeSnapShotAsync() results. This allows their use with the FileSystem API.
Some FileSystem functions are able to read from (but not write to) other locations.
SAF URI
A SAF URI is a URI that is compatible with the Storage Access Framework. It should look like this content://com.android.externalstorage.*.
The easiest way to obtain such URI is by requestDirectoryPermissionsAsync method.
Constants
Type: string | null
URI to the directory where assets bundled with the application are stored.
Type: string | null
file:// URI pointing to the directory where temporary files used by this app will be stored.
Files stored here may be automatically deleted by the system when low on storage.
Example uses are for downloaded or generated files that the app just needs for one-time usage.
Type: string | null
file:// URI pointing to the directory where user documents for this app will be stored.
Files stored here will remain until explicitly deleted by the app. Ends with a trailing /.
Example uses are for files the user saves that they expect to see again.
Classes
Type: Class extends FileSystemCancellableNetworkTask<DownloadProgressData>
DownloadResumable Properties
DownloadResumable Methods
Promise<void>Download the contents at a remote URI to a file in the app's file system.
Promise<FileSystemDownloadResult | undefined>Returns a Promise that resolves to FileSystemDownloadResult object, or to undefined when task was cancelled.
Pause the current download operation. resumeData is added to the DownloadResumable object after a successful pause operation.
Returns an object that can be saved with AsyncStorage for future retrieval (the same object that is returned from calling FileSystem.DownloadResumable.savable()).
Promise<DownloadPauseState>Returns a Promise that resolves to DownloadPauseState object.
Resume a paused download operation.
Promise<FileSystemDownloadResult | undefined>Returns a Promise that resolves to FileSystemDownloadResult object, or to undefined when task was cancelled.
Method to get the object which can be saved with AsyncStorage for future retrieval.
DownloadPauseStateReturns object in shape of DownloadPauseState type.
FileSystemCancellableNetworkTask Methods
Promise<void>Type: Class extends FileSystemCancellableNetworkTask<UploadProgressData>
UploadTask Methods
Promise<void>Promise<FileSystemUploadResult | null | undefined>Methods
Create a copy of a file or directory. Directories are recursively copied with all of their contents. It can be also used to copy content shared by other apps to local filesystem.
Promise<void>FileSystem Legacy.createDownloadResumable(uri, fileUri, options, callback, resumeData)
Create a DownloadResumable object which can start, pause, and resume a download of contents at a remote URI to a file in the app's file system.
Note: You need to call
downloadAsync(), on aDownloadResumableinstance to initiate the download. TheDownloadResumableobject has a callback that provides download progress updates. Downloads can be resumed across app restarts by usingAsyncStorageto store theDownloadResumable.savable()object for later retrieval. Thesavableobject contains the arguments required to initialize a newDownloadResumableobject to resume the download after an app restart. The directory for a local file uri must exist prior to calling this function.
DownloadResumableDelete a file or directory. If the URI points to a directory, the directory and all its contents are recursively deleted.
Promise<void>Promise<void>Download the contents at a remote URI to a file in the app's file system. The directory for a local file uri must exist prior to calling this function.
Promise<FileSystemDownloadResult>Returns a Promise that resolves to a FileSystemDownloadResult object.
Example
FileSystem.downloadAsync( 'http://techslides.com/demos/sample-videos/small.mp4', FileSystem.documentDirectory + 'small.mp4' ) .then(({ uri }) => { console.log('Finished downloading to ', uri); }) .catch(error => { console.error(error); });
Takes a file:// URI and converts it into content URI (content://) so that it can be accessed by other applications outside of Expo.
Promise<string>Returns a Promise that resolves to a string containing a content:// URI pointing to the file.
The URI is the same as the fileUri input parameter but in a different format.
Example
FileSystem.getContentUriAsync(uri).then(cUri => { console.log(cUri); IntentLauncher.startActivityAsync('android.intent.action.VIEW', { data: cUri, flags: 1, }); });
Gets the available internal disk storage size, in bytes. This returns the free space on the data partition that hosts all of the internal storage for all apps on the device.
Promise<number>Returns a Promise that resolves to the number of bytes available on the internal disk.
Gets total internal disk storage size, in bytes. This is the total capacity of the data partition that hosts all the internal storage for all apps on the device.
Promise<number>Returns a Promise that resolves to a number that specifies the total internal disk storage capacity in bytes.
Read the entire contents of a file as a string. Binary will be returned in raw format, you will need to append data:image/png;base64, to use it as Base64.
Promise<string>A Promise that resolves to a string containing the entire contents of the file.
Enumerate the contents of a directory.
Promise<string[]>A Promise that resolves to an array of strings, each containing the name of a file or directory contained in the directory at fileUri.
Upload the contents of the file pointed by fileUri to the remote url.
Promise<FileSystemUploadResult>Returns a Promise that resolves to FileSystemUploadResult object.
Example
Client
import * as FileSystem from 'expo-file-system/legacy'; try { const response = await FileSystem.uploadAsync(`http://192.168.0.1:1234/binary-upload`, fileUri, { fieldName: 'file', httpMethod: 'PATCH', uploadType: FileSystem.FileSystemUploadType.BINARY_CONTENT, }); console.log(JSON.stringify(response, null, 4)); } catch (error) { console.log(error); }
Server
Refer to the "Server: Handling multipart requests" example - there is code for a simple Node.js server.
Namespaces
The StorageAccessFramework is a namespace inside of the expo-file-system module, which encapsulates all functions which can be used with SAF URIs.
You can read more about SAF in the Android documentation.
Example
Basic Usage
import { StorageAccessFramework } from 'expo-file-system'; // Requests permissions for external directory const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync(); if (permissions.granted) { // Gets SAF URI from response const uri = permissions.directoryUri; // Gets all files inside of selected directory const files = await StorageAccessFramework.readDirectoryAsync(uri); alert(`Files inside ${uri}:\n\n${JSON.stringify(files)}`); }
Migrating an album
import * as MediaLibrary from 'expo-media-library'; import * as FileSystem from 'expo-file-system/legacy'; const { StorageAccessFramework } = FileSystem; async function migrateAlbum(albumName: string) { // Gets SAF URI to the album const albumUri = StorageAccessFramework.getUriForDirectoryInRoot(albumName); // Requests permissions const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync(albumUri); if (!permissions.granted) { return; } const permittedUri = permissions.directoryUri; // Checks if users selected the correct folder if (!permittedUri.includes(albumName)) { return; } const mediaLibraryPermissions = await MediaLibrary.requestPermissionsAsync(); if (!mediaLibraryPermissions.granted) { return; } // Moves files from external storage to internal storage await StorageAccessFramework.moveAsync({ from: permittedUri, to: FileSystem.documentDirectory!, }); const outputDir = FileSystem.documentDirectory! + albumName; const migratedFiles = await FileSystem.readDirectoryAsync(outputDir); // Creates assets from local files const [newAlbumCreator, ...assets] = await Promise.all( migratedFiles.map<Promise<MediaLibrary.Asset>>( async fileName => await MediaLibrary.createAssetAsync(outputDir + '/' + fileName) ) ); // Album was empty if (!newAlbumCreator) { return; } // Creates a new album in the scoped directory const newAlbum = await MediaLibrary.createAlbumAsync(albumName, newAlbumCreator, false); if (assets.length) { await MediaLibrary.addAssetsToAlbumAsync(assets, newAlbum, false); } }
StorageAccessFramework Methods
Gets a SAF URI pointing to a folder in the Android root directory. You can use this function to get URI for
StorageAccessFramework.requestDirectoryPermissionsAsync() when you trying to migrate an album. In that case, the name of the album is the folder name.
stringReturns a SAF URI to a folder.
Allows users to select a specific directory, granting your app access to all of the files and sub-directories within that directory.
Returns a Promise that resolves to FileSystemRequestDirectoryPermissionsResult object.
Types
Deprecated: use
FileSystemNetworkTaskProgressCallback<DownloadProgressData>instead.
Type: FileSystemNetworkTaskProgressCallback<DownloadProgressData>
Deprecated: Use
FileSystemDownloadResultinstead.
Type: FileSystemDownloadResult
Literal type: string
Acceptable values are: 'POST' | 'PUT' | 'PATCH'
Type: object shaped as below:
Or object shaped as below:
Type: UploadOptionsBinary | UploadOptionsMultipart extended by:
Enums
These values can be used to define how file system data is read / written.
These values can be used to define how sessions work on iOS.
FileSystemSessionType.BACKGROUND = 0Using this mode means that the downloading/uploading session on the native side will work even if the application is moved to background. If the task completes while the application is in background, the Promise will be either resolved immediately or (if the application execution has already been stopped) once the app is moved to foreground again.
Note: The background session doesn't fail if the server or your connection is down. Rather, it continues retrying until the task succeeds or is canceled manually.
FileSystemUploadType.BINARY_CONTENT = 0The file will be sent as a request's body. The request can't contain additional data.
FileSystemUploadType.MULTIPART = 1An RFC 2387-compliant request body. The provided file will be encoded into HTTP request.
This request can contain additional data represented by UploadOptionsMultipart type.
Supported URI schemes
In this table, you can see what type of URI can be handled by each method. For example, if you have an URI, which begins with content://, you cannot use FileSystem.readAsStringAsync(), but you can use FileSystem.copyAsync() which supports this scheme.
On Android no scheme defaults to a bundled resource.
Permissions
Android
The following permissions are added automatically through this library's AndroidManifest.xml.
iOS
No permissions required.