Back to Expo

FileSystem

docs/pages/versions/v55.0.0/sdk/filesystem.mdx

latest7.7 KB
Original Source

import APISection from '/components/plugins/APISection'; import { APIInstallSection } from '/components/plugins/InstallSection'; import { Collapsible } from '/ui/components/Collapsible'; import { ConfigReactNative, ConfigPluginExample, ConfigPluginProperties, } from '/ui/components/ConfigSection'; import { CODE } from '~/ui/components/Text';

expo-file-system provides access to files and directories stored on a device or bundled as assets into the native project. It also allows downloading files from the network.

Installation

<APIInstallSection />

Configuration in app config

You can configure expo-file-system using its built-in config plugin if you use config plugins in your project (Continuous Native Generation (CNG)). The plugin allows you to configure various properties that cannot be set at runtime and require building a new app binary to take effect. If your app does not use CNG, then you'll need to manually configure the library.

<ConfigPluginExample>
json
{
  "expo": {
    "plugins": [
      [
        "expo-file-system",
        {
          "supportsOpeningDocumentsInPlace": true,
          "enableFileSharing": true
        }
      ]
    ]
  }
}
</ConfigPluginExample>

<ConfigPluginProperties properties={[ { name: 'supportsOpeningDocumentsInPlace', platform: 'ios', description: 'A boolean to enable LSSupportsOpeningDocumentsInPlace in Info.plist. This allows the app to open documents in place.', default: 'false', }, { name: 'enableFileSharing', platform: 'ios', description: "A boolean to enable UIFileSharingEnabled in Info.plist. This enables file sharing in the iOS Files app, making the app's Documents directory accessible to users through the Files app, iTunes File Sharing, and other file management tools.", default: 'false', }, ]} />

<ConfigReactNative>

If you're not using Continuous Native Generation (CNG) or you're using native ios project manually, then you need to add the LSSupportsOpeningDocumentsInPlace and UIFileSharingEnabled keys to your project's ios/[app]/Info.plist:

xml
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
</ConfigReactNative>

Usage

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

The File and Directory instances hold a reference to a file, content, or asset URI.

The file or directory does not need to exist — an error will be thrown from the constructor only if the wrong class is used to represent an existing path (so if you try to create a File instance passing a path to an already existing directory).

Features

  • Both synchronous and asynchronous, read and write access to file contents
  • Creation, modification and deletion
  • Available properties, such as type, size, creationDate, and more
  • Ability to read and write files as streams or using the FileHandle class
  • Easy file download/upload using downloadFileAsync or expo/fetch

Examples

<Collapsible summary="Writing and reading text files">
ts
import { File, Paths } from 'expo-file-system';

try {
  const file = new File(Paths.cache, 'example.txt');
  file.create(); // can throw an error if the file already exists or no permission to create it
  file.write('Hello, world!');
  console.log(file.textSync()); // Hello, world!
} catch (error) {
  console.error(error);
}
</Collapsible> <Collapsible summary="Picking files using system pickers">

Usage with expo-document-picker:

ts
import { File } from 'expo-file-system';
import * as DocumentPicker from 'expo-document-picker';

try {
  const result = await DocumentPicker.getDocumentAsync({ copyToCacheDirectory: true });
  if (!result.canceled) {
    const { uri } = result.assets[0];
    const file = new File(uri);
    console.log(file.textSync());
  }
} catch (error) {
  console.error(error);
}

Using the built-in pickFileAsync or pickDirectoryAsync method on Android:

ts
import { File } from 'expo-file-system';

try {
  const file = new File.pickFileAsync();
  console.log(file.textSync());
} catch (error) {
  console.error(error);
}
</Collapsible> <Collapsible summary="Downloading files">

Using downloadFileAsync:

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

const url = 'https://pdfobject.com/pdf/sample.pdf';
const destination = new Directory(Paths.cache, 'pdfs');
try {
  destination.create();
  const output = await File.downloadFileAsync(url, destination);
  console.log(output.exists); // true
  console.log(output.uri); // path to the downloaded file, e.g., '${cacheDirectory}/pdfs/sample.pdf'
} catch (error) {
  console.error(error);
}

Or using expo/fetch:

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

const url = 'https://pdfobject.com/pdf/sample.pdf';
const response = await fetch(url);
const src = new File(Paths.cache, 'file.pdf');
src.write(await response.bytes());
</Collapsible>

<Collapsible summary={<>Uploading files using <CODE>expo/fetch</CODE></>}>

You can upload files as blobs directly with fetch built into the Expo package:

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

const file = new File(Paths.cache, 'file.txt');
file.write('Hello, world!');

const response = await fetch('https://example.com', {
  method: 'POST',
  body: file,
});

Or using the FormData constructor:

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

const file = new File(Paths.cache, 'file.txt');
file.write('Hello, world!');
const formData = new FormData();
formData.append('data', file);
const response = await fetch('https://example.com', {
  method: 'POST',
  body: formData,
});
</Collapsible> <Collapsible summary="Moving and copying files">
ts
import { Directory, File, Paths } from 'expo-file-system';
try {
  const file = new File(Paths.document, 'example.txt');
  file.create();
  console.log(file.uri); // '${documentDirectory}/example.txt'
  const copiedFile = new File(Paths.cache, 'example-copy.txt');
  file.copy(copiedFile);
  console.log(copiedFile.uri); // '${cacheDirectory}/example-copy.txt'
  file.move(Paths.cache);
  console.log(file.uri); // '${cacheDirectory}/example.txt'
  file.move(new Directory(Paths.cache, 'newFolder'));
  console.log(file.uri); // '${cacheDirectory}/newFolder/example.txt'
} catch (error) {
  console.error(error);
}
</Collapsible> <Collapsible summary="Using legacy FileSystem API">
ts
import * as FileSystem from 'expo-file-system/legacy';
import { File, Paths } from 'expo-file-system';

try {
  const file = new File(Paths.cache, 'example.txt');
  const content = await FileSystem.readAsStringAsync(file.uri);
  console.log(content);
} catch (error) {
  console.error(error);
}
</Collapsible> <Collapsible summary="Listing directory contents recursively">
ts
import { Directory, Paths } from 'expo-file-system';

function printDirectory(directory: Directory, indent: number = 0) {
  console.log(`${' '.repeat(indent)} + ${directory.name}`);
  const contents = directory.list();
  for (const item of contents) {
    if (item instanceof Directory) {
      printDirectory(item, indent + 2);
    } else {
      console.log(`${' '.repeat(indent + 2)} - ${item.name} (${item.size} bytes)`);
    }
  }
}

try {
  printDirectory(new Directory(Paths.cache));
} catch (error) {
  console.error(error);
}
</Collapsible>

API

<APISection packageName="expo-file-system" apiName="FileSystem" />