Expo file system not working in API 28 & below

I am using Expo SDK 47,
I try to implement the PDF and Excel file download from server, I can able to achive this and working on latest versions of android devices.
But when i try to check with android API 28, its not working.

Hi @karthikeyan_reacteas

Please explain what you mean by “its not working”.

Do you get any useful error messages in the device logs (by running adb logcat -d after the error happens)?
Can you post some example code that demonstrates the problem?

Yes, Here I attached my code which I tried. same code working fine in API 30 & 31
But when I test in API 27/28/29 its not working .I got the below log.

I make request to server & server return the base 64 content so once user want to store/download the file means they can able to download. so basic before download they choose the location when they want to download files.

once they choose download folder(API 28) its not download its shows like,

Error: Location ‘content://com.android.providers.downloads.documents/tree/downloads’ isn’t writable.

Also If they want to change the location means its not possible,

Code:

export async function createFileUsingBase64TargetAbove11(filesBase64, config) {
  const result = { uri: undefined };
  try {
    let setting = await settings().then((setting) => {
      return setting;
    });
    await MediaLibrary.requestPermissionsAsync();
    let directoryUri = setting.downloadsFolder;
    if (setting.downloadsFolder == null) {
      const permission =
        await StorageAccessFramework.requestDirectoryPermissionsAsync();
      if (!permission.granted) {
        return;
      }
      settings({
        downloadsFolder: permission.granted ? permission.directoryUri : null,
      });
      directoryUri = permission.directoryUri;
    }

    await StorageAccessFramework.createFileAsync(
      directoryUri,
      config._fileName === undefined ? "MyFile" : config._fileName,
      MIME_TYPES[config._fileType]
    ).then((uri) => {
      console.log(
        "fileInfo:" +
          directoryUri +
          "\n " +
          uri +
          "\n " +
          config._fileName +
          " " +
          MIME_TYPES[config._fileType]
      );
      FileSystem.writeAsStringAsync(uri, filesBase64, {
        encoding: FileSystem.EncodingType.Base64,
      });
      result.uri = uri;
    });
  } catch (e) {
    console.log("downloadPDF: " + e);
  }
  return result;
}

I am using expo file system and expo-sharing

OK. Maybe try stripping the code down to the bare minimum to find where the problem is happening. e.g.:

export async function writeContent() {
  const filename = "test.txt";
  const content = "SGVsbG8sIFdvcmxkIQ==";

  try {
    await MediaLibrary.requestPermissionsAsync();
    let directoryUri = "file:///...";

    await StorageAccessFramework.createFileAsync(
      directoryUri,
      filename,
      "text/plain"
    ).then((uri) => {
      console.log(`fileInfo: ${directoryUri} ${uri} ${filename}`);
      FileSystem.writeAsStringAsync(uri, content, {
        encoding: FileSystem.EncodingType.Base64,
      });
    });
  } catch (e) {
    console.log("Write failed: " + e);
  }
}

If that works, try making small additions until the problem starts happening again. What small change causes the problem to appear? Or what’s the minimum amount of code that demonstrates the problem and which part of the code is causing the problem?

Same error occurs can you plz help on this.

Ah, I see that the documentation says that this only for Android 11+ (which corresponds with Android SDK 30)

then how to handle for other versions ?
can we use expo or other better programming language ?
In expo lot of limitation for simple process

I’m not sure that’s true.

I have not personally needed this functionality before, so I don’t know what you need to do to get it to work.

If you can show me how to do it in a plain React Native app then we should be able to figure out how to do it in a managed Expo app too.

Plz create the empty expo project.
then add lib (expo file system)
my file content is base64
I need to create a file(PDF) and add this base64 string into my pdf file.
plz test with API 28 and below.

Note: dont try to download the pdf from https url bcz its working.

Saving some content to a file is fine. What you are trying to do is save it to the Downloads directory. I am just a normal Expo user and I do not have time right now to go looking for solutions for you. If you find a solution for React Native I can probably help to make it work in an Expo app.

OKay fine .Thanks man.

Note: Incase in your App contains download option means don’t use expo,
use only react native. Expo had limited access for folder access in below API 28

That statement is inaccurate.

If you want to download something you can absolutely do it with an Expo app using Expo’s FileSystem module. But it seems you might need to download it to the FileSystem.documentDirectory or FileSystem.cacheDirectory if the app is running on an older version of Android.

As far as I can tell, the Storage Access Framework on older versions of Android does not allow write access to the Downloads directory. i.e. an Android limitation rather than an Expo limitation.

I spent a few minutes looking into this and it seems a lot more complicated than it should be. Again because of Android and not Expo.

You might be able to get it to work by avoiding the SAF for older versions of Android and using rn-fetch-blob or react-native-fs. For newer versions of Android you can presumably do what you’re doing currently.

As I said before, if you find out how to do it in React Native (or maybe even in a native app) we should be able to get it to work in an Expo app.

So, we need to manage the two different libs(expo file system for Expo , react-native-fs for react native) If we develop app for below Android 6 right ?

If you need react-native-fs to support some versions of Android then maybe you could just use that for everything. But if you need `expo-file-system’ for certain functionality in newer versions of Android, then sure, you could use both.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.