Skip to main content

expo-file-system

Version: 55.0.6 Provides access to the local file system on the device. Read, write, delete files and directories, download files, and manage app storage with a modern, Promise-based API.

Installation

npx expo install expo-file-system

Usage

import * as FileSystem from 'expo-file-system';

// Modern API (Recommended)
import { Paths, File, Directory } from 'expo-file-system';

const file = new File(Paths.cache, 'notes.txt');
await file.create();
await file.write('Hello, World!');
const content = await file.text();

Modern API (v55+)

Paths

Access system directories:
Paths.cache
Directory
Cache directory – files can be deleted by the system
const cacheDir = Paths.cache;
const file = new File(cacheDir, 'temp.json');
Paths.document
Directory
Document directory – persistent storage safe from system deletion
const docDir = Paths.document;
const file = new File(docDir, 'data.db');
Paths.bundle
Directory
Bundle directory – contains assets bundled with the app (read-only)
const bundleDir = Paths.bundle;
const asset = new File(bundleDir, 'config.json');

File Class

Represents a file on the filesystem:
import { File, Paths } from 'expo-file-system';

const file = new File(Paths.document, 'notes', 'note.txt');

Methods

file.create()
() => Promise<void>
Creates the file if it doesn’t exist
file.write(content)
(content: string | Uint8Array) => Promise<void>
Writes content to the file
await file.write('Hello, World!');
await file.write(new Uint8Array([1, 2, 3]));
file.text()
() => Promise<string>
Reads file content as text
const content = await file.text();
file.bytes()
() => Promise<Uint8Array>
Reads file content as bytes
const bytes = await file.bytes();
file.delete()
() => Promise<void>
Deletes the file
file.exists()
() => Promise<boolean>
Checks if the file exists
file.copy(destination)
(destination: File | Directory) => Promise<File>
Copies the file to a new location
const newFile = await file.copy(Paths.cache);
file.move(destination)
(destination: File | Directory) => Promise<File>
Moves the file to a new location

Properties

file.uri
string
The file URI (e.g., file:///path/to/file.txt)
file.name
string
File name with extension
file.extension
string
File extension (e.g., .txt, .json)
file.parentDirectory
Directory
The directory containing this file
file.size
number
File size in bytes

Directory Class

Represents a directory on the filesystem:
import { Directory, Paths } from 'expo-file-system';

const dir = new Directory(Paths.document, 'myFolder');

Methods

dir.create()
() => Promise<void>
Creates the directory if it doesn’t exist
dir.delete()
() => Promise<void>
Deletes the directory and its contents
dir.exists()
() => Promise<boolean>
Checks if the directory exists
dir.list()
() => (File | Directory)[]
Lists contents of the directory
const contents = dir.list();
for (const item of contents) {
  if (item instanceof File) {
    console.log('File:', item.name);
  } else {
    console.log('Directory:', item.name);
  }
}
dir.createFile(name, mimeType)
(name: string, mimeType?: string) => File
Creates a new file in this directory
const file = dir.createFile('data.json', 'application/json');
dir.createDirectory(name)
(name: string) => Directory
Creates a new subdirectory
const subdir = dir.createDirectory('subfolder');

Properties

dir.uri
string
The directory URI
dir.name
string
Directory name
dir.parentDirectory
Directory
The parent directory

Download Files

File.downloadFileAsync(url, destination, options)
static
Downloads a file from a URL
const file = await File.downloadFileAsync(
  'https://example.com/file.pdf',
  Paths.document,
  {
    headers: { 'Authorization': 'Bearer token' }
  }
);

Examples

Read and Write Text Files

import { File, Paths } from 'expo-file-system';

// Write to a file
const file = new File(Paths.document, 'notes.txt');
await file.write('My notes content');

// Read from a file
const content = await file.text();
console.log(content); // "My notes content"

// Append to a file
const existingContent = await file.text();
await file.write(existingContent + '\nNew line');

Work with JSON

import { File, Paths } from 'expo-file-system';

interface UserData {
  name: string;
  email: string;
}

const dataFile = new File(Paths.document, 'user-data.json');

// Write JSON
const userData: UserData = {
  name: 'John Doe',
  email: 'john@example.com'
};
await dataFile.write(JSON.stringify(userData, null, 2));

// Read JSON
const json = await dataFile.text();
const loaded: UserData = JSON.parse(json);
console.log(loaded.name); // "John Doe"

Create Directory Structure

import { Directory, File, Paths } from 'expo-file-system';

// Create nested directories
const appData = new Directory(Paths.document, 'myapp');
await appData.create();

const imagesDir = new Directory(appData, 'images');
await imagesDir.create();

const cacheDir = new Directory(appData, 'cache');
await cacheDir.create();

// Create file in subdirectory
const configFile = new File(appData, 'config.json');
await configFile.write(JSON.stringify({ version: '1.0' }));

List Directory Contents

import { Directory, File, Paths } from 'expo-file-system';

const dir = new Directory(Paths.document);
const contents = dir.list();

for (const item of contents) {
  if (item instanceof File) {
    console.log(`File: ${item.name} (${item.size} bytes)`);
  } else if (item instanceof Directory) {
    console.log(`Directory: ${item.name}`);
  }
}

Download and Save File

import { File, Paths } from 'expo-file-system';

async function downloadImage(url: string) {
  const file = await File.downloadFileAsync(
    url,
    Paths.document,
    {
      headers: {
        'User-Agent': 'MyApp/1.0'
      }
    }
  );
  
  console.log('Downloaded to:', file.uri);
  return file;
}

await downloadImage('https://example.com/photo.jpg');

Copy and Move Files

import { File, Paths } from 'expo-file-system';

// Create a file
const original = new File(Paths.cache, 'temp.txt');
await original.write('Temporary data');

// Copy to documents (persistent storage)
const persistent = await original.copy(Paths.document);

// Move file to new location
const renamed = await persistent.move(
  new File(Paths.document, 'permanent.txt')
);

// Delete original cache file
await original.delete();

Check File Existence

import { File, Paths } from 'expo-file-system';

const file = new File(Paths.document, 'settings.json');

if (await file.exists()) {
  const data = await file.text();
  console.log('Settings loaded:', data);
} else {
  // Create default settings
  await file.write(JSON.stringify({ theme: 'light' }));
}

Binary Data Handling

import { File, Paths } from 'expo-file-system';

// Write binary data
const binaryFile = new File(Paths.document, 'data.bin');
const bytes = new Uint8Array([72, 101, 108, 108, 111]); // "Hello"
await binaryFile.write(bytes);

// Read binary data
const readBytes = await binaryFile.bytes();
console.log(readBytes); // Uint8Array(5) [72, 101, 108, 108, 111]

// Convert to string
const text = new TextDecoder().decode(readBytes);
console.log(text); // "Hello"

Stream Large Files

import { File, Paths } from 'expo-file-system';

const file = new File(Paths.document, 'large-file.txt');

// Write stream
const writable = file.writableStream();
const writer = writable.getWriter();

for (let i = 0; i < 1000; i++) {
  await writer.write(new TextEncoder().encode(`Line ${i}\n`));
}

await writer.close();

// Read stream
const readable = file.readableStream();
const reader = readable.getReader();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  console.log('Chunk:', new TextDecoder().decode(value));
}

Storage Info

import { Paths } from 'expo-file-system';

const totalSpace = Paths.totalDiskSpace;
const availableSpace = Paths.availableDiskSpace;

console.log(`Total: ${(totalSpace / 1024 / 1024 / 1024).toFixed(2)} GB`);
console.log(`Available: ${(availableSpace / 1024 / 1024 / 1024).toFixed(2)} GB`);
console.log(`Used: ${((totalSpace - availableSpace) / totalSpace * 100).toFixed(1)}%`);

Legacy API

For backwards compatibility, the legacy API is still available:
import * as FileSystem from 'expo-file-system/legacy';

// Write file
await FileSystem.writeAsStringAsync(
  FileSystem.documentDirectory + 'file.txt',
  'content'
);

// Read file
const content = await FileSystem.readAsStringAsync(
  FileSystem.documentDirectory + 'file.txt'
);
Use the modern API (File, Directory, Paths) for new projects. The legacy API is maintained for compatibility only.

TypeScript

import { File, Directory, Paths } from 'expo-file-system';

const file: File = new File(Paths.document, 'data.txt');
const dir: Directory = new Directory(Paths.cache, 'temp');

const content: string = await file.text();
const bytes: Uint8Array = await file.bytes();
const exists: boolean = await file.exists();

Platform Support

PlatformSupported
iOS
Android
Web✅ (Limited)
On web, file system access is limited to browser storage. Not all features are available.

Best Practices

  1. Use Document Directory: Store user data in Paths.document for persistence
  2. Use Cache Directory: Store temporary data in Paths.cache
  3. Check Existence: Always check if files exist before reading
  4. Handle Errors: Wrap file operations in try/catch blocks
  5. Clean Up: Delete unnecessary files from cache regularly

Resources