Reputation: 1764
I'm trying to upload an xlsx to Firestore storage, using react-native-document-picker to pick the file from ExternalStorageDirectoryPath
so when I 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],
});
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
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
but still I'm getting this error:
Permission Denial: reading com.android.externalStorageProvider uri content://com... requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()
Upvotes: 0
Views: 3933
Reputation: 31
I got the answer, I have to make a copy for cachesDirectory
, and then I can access it with fileCopyUri
as the key.
Here's the code snippet:
function pickFile() {
DocumentPicker.pickSingle({
type: [DocumentPicker.types.allFiles],
copyTo: "cachesDirectory",
})
.then((response) => {
console.log(response);
setPickedFile(response);
})
.catch((error) => {
console.error(error);
});
}
The response will be looks like this:
LOG {
"fileCopyUri": "file:///data/user/0/com.anonymous.mobileodu/cache/4f74e0ae-a628-4a19-bef5-5d18f25f51b1/Flight%20of%20the%20Pigeon.pdf",
"name": "Flight of the Pigeon.pdf",
"size": 142754,
"type": "application/pdf",
"uri": "content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2FFlight%20of%20the%20Pigeon.pdf"
}
With fileCopyUri
, I can access it via ExternalStorage and then show it with react-native-pdf
, here's the code snippet:
const DocumentDisplay = ({ url }) => {
if (!url) {
return;
}
return (
<View style={{ flex: 1, backgroundColor: "green" }}>
<Pdf
trustAllCerts={false}
source={{ uri: url, cache: true }}
style={{ flex: 1 }}
onError={(error) => {
console.error(error);
alert("Tidak bisa membuka file");
}}
/>
{/* <WebView source={{ uri: "" }} style={{ flex: 1 }} /> */}
</View>
);
};
Upvotes: 0
Reputation: 45
Here is my code that solved this issue:
handleFileSelection = async (props) => {
try {
const response = await DocumentPicker.pickMultiple({
presentationStyle: "fullScreen",
allowMultiSelection: true,
copyTo: "cachesDirectory",
});
await this.pickImageAndUpload(response[0].fileCopyUri);
} catch (err) {
console.warn(err);
}
};
pickImageAndUpload = async (uri) => {
const uploadTask = storage()
.ref()
.child(`/usersChatImages/${Date.now()}`)
.putFile(uri);
uploadTask.on(
"state_changed",
(snapshot) => {
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
},
(error) => {
alert("error uploading image");
},
() => {
uploadTask.snapshot.ref
.getDownloadURL()
.then((downloadURL) => {
alert(downloadURL);
})
.catch((err) => {
alert("YESSS");
});
}
);
};
Upvotes: 4
Reputation: 111
I had a similar problem with the frameworks Qt with the last android SDK version, I've fixed the problem by adding requestLegacyExternalStorage in the manifest (pat Application):
<application
android:requestLegacyExternalStorage="true"
android:hardwareAccelerated="true"
android:name="org.qtproject.qt5.android.bindings.QtApplication"
//...
/>
it's related to a recent change in the permission system: https://developer.android.com/about/versions/11/privacy/storage
Upvotes: 2
Reputation: 26
const res = await DocumentPicker.pickSingle({
type: [DocumentPicker.types.allFiles],
copyTo: 'cachesDirectory',
});
let fileCopyUri = res.fileCopyUri
const filename = fileCopyUri.substring(fileCopyUri.lastIndexOf('/') + 1);
const task = storage().ref(filename).putFile(fileCopyUri);
// add "copyTo: 'cachesDirectory'",
// add res.fileCopyUri
Upvotes: 0