Skip to content

Permission Denial Error when trying to upload file picked from ExternalStorageDirectoryPath to fireStore storage #387

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Saidfatah opened this issue Feb 8, 2021 · 11 comments

Comments

@Saidfatah
Copy link

I'm trying to upload a .xlsx file to firestore storage ,I'm using react-native-document-picker to pick the file from ExternalStorageDirectoryPath so when just log the files uri I don't get the error but as soon as try to upload the file it throws the error .


relevant code :

 const uploadFile=async ()=>{
        try {
          
            const res = await DocumentPicker.pick({
                type: [DocumentPicker.types.allFiles],
            });
            console.log(res.uri) //<-----works fine

            //this is what iscausing the error apparently 
            const task =  Storage().ref('catalogue/'+ res.name).putFile(res.uri);
            task.on('state_changed', 
                sn =>{},
                err=>console.log(err),
                () => {
                   console.log('excel uploaded!'+res.name)
                   Storage()
                   .ref("catalogue").child(res.name).getDownloadURL()
                   .then(url => {
                     console.log('uploaded excel url', url);
                   }).catch(err=>console.log(err))
               }
            )
            await task 
             
           
          } catch (err) {
            if (DocumentPicker.isCancel(err)) {
              // User cancelled the picker, exit any dialogs or menus and move on
            } else {
              throw err;
            }
        }
    }

`
I already included the required permissions in my AndroidManifest.xml file and rebuilt the project , although 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.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
the Error I'm getting :

Permission Denial: reading com.android.externalStorageProvider uri content://com... requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()

@joeljerushan
Copy link

Screenshot_1612974550

Im facing same issue here someone please help us please.

Upload to Firebase Storage

storageRef.putFile(file.uri).then(function(snapshot) {
            storageRef.getDownloadURL().then(function(url) {
                file.public_url = url //merge public url to file object
                console.log(url)
            }).catch(function(error) {
                console.log("error at storageRef.putFile() ", error)
            });
        }).catch(function(e) {
            console.log("Upload Error ", e)
        });

@Saidfatah
Copy link
Author

Screenshot_1612974550

Im facing same issue here someone please help us please.

Upload to Firebase Storage

storageRef.putFile(file.uri).then(function(snapshot) {
            storageRef.getDownloadURL().then(function(url) {
                file.public_url = url //merge public url to file object
                console.log(url)
            }).catch(function(error) {
                console.log("error at storageRef.putFile() ", error)
            });
        }).catch(function(e) {
            console.log("Upload Error ", e)
        });

its really annoying that we have to deal with this

@vonovak
Copy link
Member

vonovak commented Feb 10, 2021

hello @Saidfatah

its really annoying that we have to deal with this

you're more than welcome to investigate this and open a PR with a fix, it'll be appreciated, thank you

@furkansahinfs
Copy link

furkansahinfs commented Feb 12, 2021

If the solution below doesn't work, have a look at other comment. It perfectly works :

#387 (comment)

Firebase Storage is not suitable with content://com uri.

So firstly do npm install --save rn-fetch-blob https://github.com/joltup/rn-fetch-blob then import RNFetchBlob from 'rn-fetch-blob';

After that use this function below to get the uri which is suitable for firebase storage

getPathForFirebaseStorage = async(uri) => {
        if (Platform.OS === 'ios')
        {
            return uri
        } 
        const stat = await RNFetchBlob.fs.stat(uri)
        return stat.path
}

stat.path returns "data/0/..." path for the given uri.

At the end have a look at the main code below

 const documentUri= await this.getPathForFirebaseStorage(document.uri)
 const storageRef = firebase.storage().ref();
 await storageRef
                    .child( '/documents/' + document.name)
                    .putFile(documentUri).then((snapshot) => {
                        console.log('has been successfully uploaded.');
                    }).catch((e) => console.log('uploading image error => ', e));                   

We get the suitable uri from this.getPathForFirebaseStorage(document.uri) function. document.uri is res.uri in your code and that function returns a new uri which is called as documentUri. Put the documentUri to the storage function.

Briefly ;
1- just add the getPathForFirebaseStorage function.
2- After the line console.log(res.uri) //<-----works fine,
add
const documentUri= await this.getPathForFirebaseStorage(res.uri)
3- Change the parameter res.uri -> documentUri in putFile :
const task = Storage().ref('catalogue/'+ res.name).putFile(documentUri);

I think it works. I have faced with that problem and RNFetchBlob solved it.

Reference : https://github.com/invertase/react-native-firebase/issues/2558#issuecomment-534955902[Link](https://github.com/rnmods/react-native-document-picker/issues/387#issuecomment-790977119)

@victorrik
Copy link

exist another post about this, recently i found this packages as alternative to rn-fetch-blob

https://github.com/flyerhq/react-native-android-uri-path

it works for me

@HappyGick
Copy link

Firebase Storage is not suitable with content://com uri.

So firstly do npm install --save rn-fetch-blob https://github.com/joltup/rn-fetch-blob then import RNFetchBlob from 'rn-fetch-blob';

After that use this function below to get the uri which is suitable for firebase storage

getPathForFirebaseStorage = async(uri) => {
        if (Platform.OS === 'ios')
        {
            return uri
        } 
        const stat = await RNFetchBlob.fs.stat(uri)
        return stat.path
}

stat.path returns "data/0/..." path for the given uri.

At the end have a look at the main code below

 const documentUri= await this.getPathForFirebaseStorage(document.uri)
 const storageRef = firebase.storage().ref();
 await storageRef
                    .child( '/documents/' + document.name)
                    .putFile(documentUri).then((snapshot) => {
                        console.log('has been successfully uploaded.');
                    }).catch((e) => console.log('uploading image error => ', e));                   

We get the suitable uri from this.getPathForFirebaseStorage(document.uri) function. document.uri is res.uri in your code and that function returns a new uri which is called as documentUri. Put the documentUri to the storage function.

Briefly ;
1- just add the getPathForFirebaseStorage function.
2- After the line console.log(res.uri) //<-----works fine,
add
const documentUri= await this.getPathForFirebaseStorage(res.uri)
3- Change the parameter res.uri -> documentUri in putFile :
const task = Storage().ref('catalogue/'+ res.name).putFile(documentUri);

I think it works. I have faced with that problem and RNFetchBlob solved it.

Reference : invertase/react-native-firebase#2558 (comment)

When doing that I get this error:

Error: [storage/unknown] /storage/emulated/0/Download/3497-normal.jpg: open failed: EACCES (Permission denied)
NativeFirebaseError: [storage/unknown] /storage/emulated/0/Download/3497-normal.jpg: open failed: EACCES (Permission denied)

Despite having requested READ_EXTERNAL_STORAGE with the PermissionsAndroid API (and it's also set in the AndroidManifest). For now I'm using a solution I read here, but as someone else said later in that thread, it takes up a lot of memory for large files.

@Saidfatah
Copy link
Author

Firebase Storage is not suitable with content://com uri.
So firstly do npm install --save rn-fetch-blob https://github.com/joltup/rn-fetch-blob then import RNFetchBlob from 'rn-fetch-blob';
After that use this function below to get the uri which is suitable for firebase storage

getPathForFirebaseStorage = async(uri) => {
        if (Platform.OS === 'ios')
        {
            return uri
        } 
        const stat = await RNFetchBlob.fs.stat(uri)
        return stat.path
}

stat.path returns "data/0/..." path for the given uri.
At the end have a look at the main code below

 const documentUri= await this.getPathForFirebaseStorage(document.uri)
 const storageRef = firebase.storage().ref();
 await storageRef
                    .child( '/documents/' + document.name)
                    .putFile(documentUri).then((snapshot) => {
                        console.log('has been successfully uploaded.');
                    }).catch((e) => console.log('uploading image error => ', e));                   

We get the suitable uri from this.getPathForFirebaseStorage(document.uri) function. document.uri is res.uri in your code and that function returns a new uri which is called as documentUri. Put the documentUri to the storage function.
Briefly ;
1- just add the getPathForFirebaseStorage function.
2- After the line console.log(res.uri) //<-----works fine,
add
const documentUri= await this.getPathForFirebaseStorage(res.uri)
3- Change the parameter res.uri -> documentUri in putFile :
const task = Storage().ref('catalogue/'+ res.name).putFile(documentUri);
I think it works. I have faced with that problem and RNFetchBlob solved it.
Reference : invertase/react-native-firebase#2558 (comment)

When doing that I get this error:

Error: [storage/unknown] /storage/emulated/0/Download/3497-normal.jpg: open failed: EACCES (Permission denied)
NativeFirebaseError: [storage/unknown] /storage/emulated/0/Download/3497-normal.jpg: open failed: EACCES (Permission denied)

Despite having requested READ_EXTERNAL_STORAGE with the PermissionsAndroid API (and it's also set in the AndroidManifest). For now I'm using a solution I read here, but as someone else said later in that thread, it takes up a lot of memory for large files.

well thankyou or the suggestion in my case my files are very small 1mb to 20mb

@furkansahinfs
Copy link

furkansahinfs commented Mar 4, 2021

Firebase Storage is not suitable with content://com uri.
So firstly do npm install --save rn-fetch-blob https://github.com/joltup/rn-fetch-blob then import RNFetchBlob from 'rn-fetch-blob';
After that use this function below to get the uri which is suitable for firebase storage

getPathForFirebaseStorage = async(uri) => {
        if (Platform.OS === 'ios')
        {
            return uri
        } 
        const stat = await RNFetchBlob.fs.stat(uri)
        return stat.path
}

stat.path returns "data/0/..." path for the given uri.
At the end have a look at the main code below

 const documentUri= await this.getPathForFirebaseStorage(document.uri)
 const storageRef = firebase.storage().ref();
 await storageRef
                    .child( '/documents/' + document.name)
                    .putFile(documentUri).then((snapshot) => {
                        console.log('has been successfully uploaded.');
                    }).catch((e) => console.log('uploading image error => ', e));                   

We get the suitable uri from this.getPathForFirebaseStorage(document.uri) function. document.uri is res.uri in your code and that function returns a new uri which is called as documentUri. Put the documentUri to the storage function.
Briefly ;
1- just add the getPathForFirebaseStorage function.
2- After the line console.log(res.uri) //<-----works fine,
add
const documentUri= await this.getPathForFirebaseStorage(res.uri)
3- Change the parameter res.uri -> documentUri in putFile :
const task = Storage().ref('catalogue/'+ res.name).putFile(documentUri);
I think it works. I have faced with that problem and RNFetchBlob solved it.
Reference : invertase/react-native-firebase#2558 (comment)

When doing that I get this error:

Error: [storage/unknown] /storage/emulated/0/Download/3497-normal.jpg: open failed: EACCES (Permission denied)
NativeFirebaseError: [storage/unknown] /storage/emulated/0/Download/3497-normal.jpg: open failed: EACCES (Permission denied)

Despite having requested READ_EXTERNAL_STORAGE with the PermissionsAndroid API (and it's also set in the AndroidManifest). For now I'm using a solution I read here, but as someone else said later in that thread, it takes up a lot of memory for large files.

You can also try that :

npm i @flyerhq/react-native-android-uri-path

import getPath from '@flyerhq/react-native-android-uri-path';

const imageUri = getPath(image.uri);
                            await storageRef
                                .child(image.name)
                                .putFile(imageUri).then((snapshot) => {
                                    console.log('Image has been successfully uploaded.')
                                }).catch((e) => console.log('uploading image error => ', e));

@furkansahinfs
Copy link

furkansahinfs commented Mar 4, 2021

Firebase Storage is not suitable with content://com uri.
So firstly do npm install --save rn-fetch-blob https://github.com/joltup/rn-fetch-blob then import RNFetchBlob from 'rn-fetch-blob';
After that use this function below to get the uri which is suitable for firebase storage

getPathForFirebaseStorage = async(uri) => {
        if (Platform.OS === 'ios')
        {
            return uri
        } 
        const stat = await RNFetchBlob.fs.stat(uri)
        return stat.path
}

stat.path returns "data/0/..." path for the given uri.
At the end have a look at the main code below

 const documentUri= await this.getPathForFirebaseStorage(document.uri)
 const storageRef = firebase.storage().ref();
 await storageRef
                    .child( '/documents/' + document.name)
                    .putFile(documentUri).then((snapshot) => {
                        console.log('has been successfully uploaded.');
                    }).catch((e) => console.log('uploading image error => ', e));                   

We get the suitable uri from this.getPathForFirebaseStorage(document.uri) function. document.uri is res.uri in your code and that function returns a new uri which is called as documentUri. Put the documentUri to the storage function.
Briefly ;
1- just add the getPathForFirebaseStorage function.
2- After the line console.log(res.uri) //<-----works fine,
add
const documentUri= await this.getPathForFirebaseStorage(res.uri)
3- Change the parameter res.uri -> documentUri in putFile :
const task = Storage().ref('catalogue/'+ res.name).putFile(documentUri);
I think it works. I have faced with that problem and RNFetchBlob solved it.
Reference : invertase/react-native-firebase#2558 (comment)

When doing that I get this error:

Error: [storage/unknown] /storage/emulated/0/Download/3497-normal.jpg: open failed: EACCES (Permission denied)
NativeFirebaseError: [storage/unknown] /storage/emulated/0/Download/3497-normal.jpg: open failed: EACCES (Permission denied)

Despite having requested READ_EXTERNAL_STORAGE with the PermissionsAndroid API (and it's also set in the AndroidManifest). For now I'm using a solution I read here, but as someone else said later in that thread, it takes up a lot of memory for large files.

well thankyou or the suggestion in my case my files are very small 1mb to 20mb

You can have a look at that comment, it perfectly works. I changed my rn-fetch code to that one. I think it is good for your error

#387 (comment)

@juned298
Copy link

If the solution below doesn't work, have a look at other comment. It perfectly works :

#387 (comment)

Firebase Storage is not suitable with content://com uri.

So firstly do npm install --save rn-fetch-blob https://github.com/joltup/rn-fetch-blob then import RNFetchBlob from 'rn-fetch-blob';

After that use this function below to get the uri which is suitable for firebase storage

getPathForFirebaseStorage = async(uri) => {
        if (Platform.OS === 'ios')
        {
            return uri
        } 
        const stat = await RNFetchBlob.fs.stat(uri)
        return stat.path
}

stat.path returns "data/0/..." path for the given uri.

At the end have a look at the main code below

 const documentUri= await this.getPathForFirebaseStorage(document.uri)
 const storageRef = firebase.storage().ref();
 await storageRef
                    .child( '/documents/' + document.name)
                    .putFile(documentUri).then((snapshot) => {
                        console.log('has been successfully uploaded.');
                    }).catch((e) => console.log('uploading image error => ', e));                   

We get the suitable uri from this.getPathForFirebaseStorage(document.uri) function. document.uri is res.uri in your code and that function returns a new uri which is called as documentUri. Put the documentUri to the storage function.

Briefly ;
1- just add the getPathForFirebaseStorage function.
2- After the line console.log(res.uri) //<-----works fine,
add
const documentUri= await this.getPathForFirebaseStorage(res.uri)
3- Change the parameter res.uri -> documentUri in putFile :
const task = Storage().ref('catalogue/'+ res.name).putFile(documentUri);

I think it works. I have faced with that problem and RNFetchBlob solved it.

Reference : [https://github.com/invertase/react-native-firebase/issues/2558#issuecomment-534955902Link](https://github.com/invertase/react-native-firebase/issues/2558#issuecomment-534955902%5BLink%5D(https://github.com/rnmods/react-native-document-picker/issues/387#issuecomment-790977119))

it's work

@vonovak
Copy link
Member

vonovak commented Oct 2, 2021

hello!

It appears that the original issue has been resolved, so I'm going to close this.

Looking at the comments, it seems that the copyTo option should work too: https://github.com/rnmods/react-native-document-picker#ios-and-android-only-copytocachesdirectory--documentdirectory

@vonovak vonovak closed this as completed Oct 2, 2021
@react-native-documents react-native-documents locked as resolved and limited conversation to collaborators Oct 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants