React Native course ยท Module 6: Photos, camera and audio

expo-file-system and expo-sharing

2 min read ยท
In this lesson3

Manage files and share them!

expo-file-system

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

// Directory paths
const documentsDir = FileSystem.documentDirectory;
const cacheDir = FileSystem.cacheDirectory;

// Downloading a file
async function downloadImage(url: string, filename: string) {
  const fileUri = `${FileSystem.documentDirectory}${filename}`;

  const downloadResumable = FileSystem.createDownloadResumable(
    url,
    fileUri,
    {},
    (progress) => {
      const percent = progress.totalBytesWritten / progress.totalBytesExpectedToWrite;
      console.log(`Downloaded: ${Math.round(percent * 100)}%`);
    }
  );

  const result = await downloadResumable.downloadAsync();
  return result?.uri;
}

// Reading a file
async function readFile(filename: string) {
  const fileUri = `${FileSystem.documentDirectory}${filename}`;
  const content = await FileSystem.readAsStringAsync(fileUri);
  return content;
}

// Writing a file
async function writeFile(filename: string, content: string) {
  const fileUri = `${FileSystem.documentDirectory}${filename}`;
  await FileSystem.writeAsStringAsync(fileUri, content);
}

// File info
async function getFileInfo(uri: string) {
  const info = await FileSystem.getInfoAsync(uri);
  console.log('Exists:', info.exists);
  console.log('Size:', info.size);
  console.log('URI:', info.uri);
  return info;
}

// Deleting
async function deleteFile(uri: string) {
  await FileSystem.deleteAsync(uri);
}

// Listing files
async function listDirectory(dir: string) {
  const files = await FileSystem.readDirectoryAsync(dir);
  return files;
}

expo-sharing

npx expo install expo-sharing
import * as Sharing from 'expo-sharing';
import * as FileSystem from 'expo-file-system';

async function shareImage(imageUri: string) {
  // Check if sharing is available
  const isAvailable = await Sharing.isAvailableAsync();
  if (!isAvailable) {
    Alert.alert('Error', 'Sharing is not available on this device');
    return;
  }

  // Share
  await Sharing.shareAsync(imageUri, {
    mimeType: 'image/jpeg',
    dialogTitle: 'Share photo',
  });
}

// Sharing from a downloaded URL
async function downloadAndShare(url: string) {
  const filename = url.split('/').pop() || 'file';
  const localUri = `${FileSystem.cacheDirectory}${filename}`;

  // Download
  await FileSystem.downloadAsync(url, localUri);

  // Share
  await Sharing.shareAsync(localUri);
}

expo-media-library

npx expo install expo-media-library
import * as MediaLibrary from 'expo-media-library';

// Save to gallery
async function saveToGallery(uri: string) {
  const { status } = await MediaLibrary.requestPermissionsAsync();
  if (status !== 'granted') return;

  const asset = await MediaLibrary.createAssetAsync(uri);

  // Optionally: add to album
  const album = await MediaLibrary.getAlbumAsync('Atlantis');
  if (album) {
    await MediaLibrary.addAssetsToAlbumAsync([asset], album, false);
  } else {
    await MediaLibrary.createAlbumAsync('Atlantis', asset, false);
  }

  Alert.alert('Success', 'Photo saved to gallery!');
}

// Get photos from gallery
async function getPhotos() {
  const { status } = await MediaLibrary.requestPermissionsAsync();
  if (status !== 'granted') return [];

  const media = await MediaLibrary.getAssetsAsync({
    mediaType: 'photo',
    first: 20,
    sortBy: MediaLibrary.SortBy.creationTime,
  });

  return media.assets;
}

These libraries give you full control over files and media!

Code for this lesson: App.tsx
import React, { useState } from 'react';
import { View, Text, Pressable, StyleSheet, Alert } from 'react-native';
import * as FileSystem from 'expo-file-system';
import * as Sharing from 'expo-sharing';

export default function App() {
  const [busy, setBusy] = useState(false);

  const downloadAndShare = async () => {
    setBusy(true);
    const url = 'https://picsum.photos/600';
    const fileUri = `${FileSystem.cacheDirectory}atlantis.jpg`;

    // TODO: download the file from the URL to fileUri:
    //   await FileSystem.downloadAsync(url, fileUri);

    // TODO: check sharing availability:
    //   const isAvailable = await Sharing.isAvailableAsync();
    //   if (!isAvailable) { Alert.alert('Error', 'Sharing not available'); return; }

    // TODO: share the downloaded file:
    //   await Sharing.shareAsync(fileUri);

    setBusy(false);
  };

  return (
    <View style={styles.container}>
      <Pressable style={styles.button} onPress={downloadAndShare} disabled={busy}>
        <Text style={styles.buttonText}>{busy ? 'Downloading...' : 'Download & share'}</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#1a5276' },
  button: { backgroundColor: '#2980b9', paddingVertical: 14, paddingHorizontal: 32, borderRadius: 8 },
  buttonText: { color: '#fff', fontSize: 16, fontWeight: '600' },
});

Docs entries used in this lesson

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. Where should you store persistent application files?

Hands-on tasks in the game

  • Horizontal ordering

    Arrange file sharing:

  • Code editor

    Complete the code with FileSystem and Sharing.

Useful articles