Reputation: 21630
THE SITUATION:
In my mobile app I need to download a file and store in the Download folder.
The download part is working fine. The file is properly downloaded from the server and stored in the following folder:
file:///storage/emulated/0/Android/data/org.cordova.MY_APP_NAME.app/my_file.pdf
But the location is not really user-friendly.
To access it I have to go to: Internal storage / Android / data / org.cordova.MY_APP_NAME.app /
So I need to move it to the main Download folder.
The file transfer is what I don't manage to do.
I know that there are already several similar questions on SO.
I have tried them all but none really worked for me, I could never see the file in the actual Download folder.
PROJECT INFO:
I am using Quasar with Vuejs and Cordova.
PLATFORM:
For the moment I am working with Android. But ideally I am looking for a solution that works for both Android and IOS.
THE CODE:
The download code:
var fileTransfer = new FileTransfer() // eslint-disable-line
var uri = encodeURI('https://MY_SERVER_PATH')
fileTransfer.download(
uri,
cordova.file.externalApplicationStorageDirectory + 'my_file.pdf',
entry => {
console.log('download complete: ' + entry.toURL())
this.moveFile(entry.toURL())
},
error => {
console.log('download error source ' + error.source)
console.log('download error target ' + error.target)
console.log('download error code' + error.code)
},
false,
{
headers: {
'Authorization': 'Basic asdasdasdasdassdasdasd'
}
}
)
The File transfer code:
moveFile(fileUri) {
window.resolveLocalFileSystemURL(
fileUri,
fileEntry => {
let newFileUri = 'file:///storage/emulated/0/Download'
window.resolveLocalFileSystemURL(
newFileUri,
dirEntry => {
fileEntry.moveTo(dirEntry, 'new_filename.pdf', this.moveFileSuccess, this.moveFileError)
},
this.moveFileError)
},
this.moveFileError)
},
moveFileSuccess(entry) {
console.log('file move success')
console.log(entry)
},
moveFileError(error) {
console.log('file move error')
console.log(error)
}
THE QUESTION:
How can I move a file to the Download folder?
Thanks
EDIT:
This is the console log of the cordova.file
object:
applicationDirectory: "file:///android_asset/"
applicationStorageDirectory: "file:///data/user/0/org.cordova.MY_APP_NAME.app/"
cacheDirectory:"file:///data/user/0/org.cordova.MY_APP_NAME.app/cache/"
dataDirectory: "file:///data/user/0/org.cordova.MY_APP_NAME.app/files/"
documentsDirectory: null
externalApplicationStorageDirectory: "file:///storage/emulated/0/Android/data/org.cordova.MY_APP_NAME.app/"
externalCacheDirectory: "file:///storage/emulated/0/Android/data/org.cordova.MY_APP_NAME.app/cache/"
externalDataDirectory: "file:///storage/emulated/0/Android/data/org.cordova.MY_APP_NAME.app/files/"
externalRootDirectory: "file:///storage/emulated/0/"
sharedDirectory: null
syncedDataDirectory: null
tempDirectory: null
Upvotes: 3
Views: 11328
Reputation: 21630
Okay I managed to resolve it.
First of all is totally unnecessary to download and then move the file. It can just be directly downloaded in the desired direction.
The correct path (in my case) was this:
cordova.file.externalRootDirectory + 'download/' + 'my_file.pdf
that correspond to: file:///storage/emulated/0/download/my_file.pdf
and that means that to find the file inside the device you have to go to: Internal Storage / Download / my_file.pdf
Add the following value in the config.xml:
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
<preference name="AndroidExtraFilesystems" value="files,files-external,documents,sdcard,root" />
It's important to check for permission using this cordova plugin: cordova-plugin-android-permissions
You can make a quick test like this:
let permissions = cordova.plugins.permissions
permissions.checkPermission(permissions.READ_EXTERNAL_STORAGE, checkPermissionCallback, null)
function checkPermissionCallback(status) {
console.log('checking permissions')
console.log(status)
}
Most probably the result is false
. And that means that we have to request permission to the user:
permissions.requestPermission(successCallback, errorCallback, permission)
In this way it will appear the alert asking for permission.
THE CODE:
To put it all together, this is the working code:
let pdfPath = 'https://MY_SERVER_PATH'
let permissions = cordova.plugins.permissions
permissions.checkPermission(permissions.READ_EXTERNAL_STORAGE, checkPermissionCallback, null)
// Checking for permissions
function checkPermissionCallback(status) {
console.log('checking permissions')
console.log(status)
if (!status.hasPermission) {
var errorCallback = function () {
console.warn('Storage permission is not turned on')
}
// Asking permission to the user
permissions.requestPermission(
permissions.READ_EXTERNAL_STORAGE,
function (status) {
if (!status.hasPermission) {
errorCallback()
} else {
// proceed with downloading
downloadFile()
}
},
errorCallback)
} else {
downloadFile()
}
}
function downloadFile() {
let filePath = cordova.file.externalRootDirectory + 'download/' + 'my_file.pdf'
let fileTransfer = new window.FileTransfer()
let uri = encodeURI(decodeURIComponent(pdfPath))
// Downloading the file
fileTransfer.download(uri, filePath,
function (entry) {
console.log('Successfully downloaded file, full path is ' + entry.fullPath)
console.log(entry)
},
function (error) {
console.log('error')
console.log(error)
},
false
)
}
Upvotes: 16
Reputation: 11224
cordova.file.externalApplicationStorageDirectory.
For that path you do not need to request any permission in manifest or require any permission at all.
But for others like external storage and so you need them.
You are #1244 with this problem this year.
Google for runtime permissions.
You can than directly download to the Download directory.
Upvotes: -1
Reputation: 122
var fileTransfer = new FileTransfer() // eslint-disable-line
var uri = encodeURI('https://MY_SERVER_PATH')
var fileURL = "///storage/emulated/0/Download";
fileTransfer.download(
uri,
fileURL+ 'your_file.pdf',
entry => {
console.log('download complete: ' + entry.toURL())
this.moveFile(entry.toURL())
},
error => {
console.log('download error source ' + error.source)
console.log('download error target ' + error.target)
console.log('download error code' + error.code)
},
false,
{
headers: {
'Authorization': 'Basic asdasdasdasdassdasdasd'
}
}
)
you can directly save downloaded file to your path
Try above code and let me know if its work.
Upvotes: 0