1
votes

I've been trying to make a simple document picker that allows the user to select a file and returns the selected file encoded in base64. For that, I'm currently using two packages :

Here is this specific bit of code :

    DocumentPicker.pick({
        type: [DocumentPicker.types.allFiles]
    })
    .then(res =>
    {
        RNFS.readFile(decodeURIComponent(res.uri), "base64").then(result =>
        {
            console.log(result)
        })
    })
    .catch(error =>
    {
        console.log(error)
    })

It works well when selecting a file from my Downloads folder, however, when I try to select a file from the "Recent" folder or from any folder that isn't related to my app, the readFile fails with the error :

Permission Denial: reading com.android.providers.media.MediaDocumentsProvider uri content://com.android.providers.media.documents/document/image:105724 from pid=22663, uid=10471 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()

From what I've read, MANAGE_DOCUMENTS is a "signature" permission and cannot be added to the manifest.xml or granted by the react native android permission API.

Is there any way I can grant or pass react-native-fs this permission, or any workaround I could use to pick any file without the error ? Am I doing this wrong ? I've tried using react-native-get-real-path to get a file uri from the content uri and fetching the content uri to get a blob, but it doesn't seem to work.

Thank you

2

2 Answers

4
votes

Answering my question since I found the problem : RNFS.readFile only works when supplied the original res.uri, you don't have to decode it via decodeURIComponent.

The correct code was :

RNFS.readFile(res.uri, "base64").then(result =>
{
    console.log(result)
})
2
votes

For anyone stuck on this issue, make sure that you don't use decodeURIComponent for Android. But you'll still have to use this for IOS. The following code snippet works on both Platforms

import { Platform } from 'react-native';
import DocumentPicker from 'react-native-document-picker';

const file = await DocumentPicker.pick();
const uri = Platform.select({
  android: file.uri,
  ios: decodeURIComponent(file.uri)?.replace?.('file://', ''),
});

const base64File = await RNFS.readFile(uri, "base64");
// Your file handling here