Skip to content
Today's Tech Byte: Downloading documents in Expo & React Native

Today's Tech Byte: Downloading documents in Expo & React Native

Posted on:November 21, 2023

In this post, we will learn how to download a document in an Expo app. We will use the expo-file-system package to download the document and the expo-sharing package to share it in iOS.

First, we need to the necessary packages:

expo install expo-file-system expo-sharing

After that, we can use the downloadAsync method from the expo-file-system package to download the document. The downloadAsync method takes two arguments: the URL of the document and the path where the document will be saved.

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

const downloadFile = async () => {
  const { uri } = await FileSystem.downloadAsync(
    "https://file-examples-com.github.io/uploads/2017/10/file-sample_150kB.pdf",
    FileSystem.documentDirectory + "small.pdf"
  );
  console.log("Finished downloading to ", uri);
};

Now to save the document in the device, the implementation depends on the platform.

iOS

We can use the shareAsync method from the expo-sharing package to save the document in the device. The shareAsync method takes one argument: the URI of the document.

import * as Sharing from "expo-sharing";

const saveFile = async uri => {
  await Sharing.shareAsync(uri);
};

Android

There are couple things we need to do to save the document in the device.

1- Request the permission to access the device storage.

2- Create a file in the device storage, and write the document in it.

const saveFile = async uri => {
  const permissions =
    await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();

  if (!permissions.granted) {
    console.log("Permission denied!");
    return;
  }

  const base64 = await FileSystem.readAsStringAsync(uri, {
    encoding: FileSystem.EncodingType.Base64,
  });

  await FileSystem.StorageAccessFramework.createFileAsync(
    permissions.directoryUri,
    "small",
    "application/pdf"
  ).then(async res => {
    await FileSystem.writeAsStringAsync(res, base64, {
      encoding: FileSystem.EncodingType.Base64,
    });
  });
};

Your final code should look like this:

import * as FileSystem from "expo-file-system";
import * as Sharing from "expo-sharing";

const downloadFile = async () => {
  const { uri } = await FileSystem.downloadAsync(
    "https://file-examples-com.github.io/uploads/2017/10/file-sample_150kB.pdf",
    FileSystem.documentDirectory + "small.pdf"
  );
  saveFile(uri);
};

const saveFile = async () => {
  if (Platform.OS === "ios") {
    await Sharing.shareAsync(uri);
  } else {
    const permissions =
      await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();

    if (!permissions.granted) {
      console.log("Permission denied!");
      return;
    }

    const base64 = await FileSystem.readAsStringAsync(uri, {
      encoding: FileSystem.EncodingType.Base64,
    });

    await FileSystem.StorageAccessFramework.createFileAsync(
      permissions.directoryUri,
      "small",
      "application/pdf"
    ).then(async res => {
      await FileSystem.writeAsStringAsync(res, base64, {
        encoding: FileSystem.EncodingType.Base64,
      });
    });
  }
};

See you in the next post! 👋