I am using ionic 3.13.1 framework. My application should allow user to work with files from device and from google drive. I am using IonicNativeFile and IonicNativeFileChooser. So, when I select file from device memory - all works good, but I cannot use that method for google drive files. My function looks like:
public OpenFile(event: Event) {
this.fileChooser.open() //Open File Chooser
.then(uri => { //get uri
console.log(`URI: ${uri}`);
( < any > window).FilePath.resolveNativePath(uri, (result) => { //Get file path in storage from uri
this.nativepath = result;
console.log(`Native Path: ${this.nativepath}`);
this.readFile(); //read data from file
this.loader = this.loadingCtrl.create({ //Create and show loader message
content: "Loading..."
});
this.loader.present();
}, (error) => {
console.log(`Looks like file from GDrive: code ${error.code} message ${error.message}`);
});
}).catch(e => console.log(e));}
The uri is: content://com.google.android.apps.docs.storage.legacy/enc%3Di2Alapnkehx4uFSbuS2U3VO_rC-nrHu3Emq8u8eF4Z9w8QvL%0A
ResolveNativePath shoud return 1 if file is in cloud, but my function returns 0 with message: Unable to resolve filesystem path. I dont't know how to fix it.
Help me, please. What should I do to get path of file?
Related
I have a simple app in native script angular for android, where I store some user-defined data into a JSON file in the app's private folder.
It actually works, but the problem is, if I copy the file to sd card and then back in the app folder, the app can't read the content of the file. Of course, I changed the permissions of the file to 600 (that's what the original file had). But it still doesn't work.
If you ask why I'm copying the file to sd card and back it's because I'm trying to solve a problem where if I update the app in play store it is unable to read the stored JSON file created by the previous version and I think that it's somehow related.
The code for saving data into file is this:
saveUsers() {
this.adresarAppky = fs.knownFolders.currentApp();
this.adresarZrodenci = this.adresarAppky.getFolder('zrodenci');
this.zrodenciFile = this.adresarZrodenci.getFile('zrodenci.json');
this.zrodenciFile.writeText(JSON.stringify(this.users))
.then(result => {
console.log('File saved');
}).catch(err => {
console.log('Error saving ' + err);
})
}
and this is code for reading the file contents
loadSavedUsers() {
this.adresarAppky = fs.knownFolders.currentApp();
this.adresarZrodenci = this.adresarAppky.getFolder('zrodenci');
if (!File.exists(path.join(this.adresarZrodenci.path, 'zrodenci.json'))) this.saveUsers();
this.zrodenciFile = this.adresarZrodenci.getFile('zrodenci.json');
this.zrodenciFile.readText()
.then(res => {
this.zrodenciData = JSON.parse(res);
console.log('Data read ' + res);
this.users = this.zrodenciData;
this.emitSelectedUser();
}).catch(err => {
console.log('Error reading file ' + err);
});
}
The line with console.log('Error reading file') outputs this error - ReadTextTask returns no result.
I'm trying to save a video record from the camera to cordova.file.dataDirectory but I get a NOT_FOUND_ERR when I try to copy the newly created file from the gallery.
I'm using cordova-plugin-media-capture to record the video, which then is saved to the user's gallery. But when I get the FileEntry using window.resolveLocalFileSystemURL and try to use entry.copyTo() the NOT_FOUND_ERR error is thrown.
A cut down / messy version of my code is below:
// Capture Video
navigator.device.capture.captureVideo(onCaptureSuccess, onError, { limit: 1 });
onCaptureSuccess(mediaFiles: any[]) {
// Get video Path
let videoPath = mediaFiles[0].fullPath;
// Get the actual video file
window.resolveLocalFileSystemURL(videoPath, entry => {
// Get the cordova.file.dataDirectory directory entry
window.resolveLocalFileSystemURL(cordova.file.dataDirectory, directoryEntry => {
// Get / Create the 'videos' directory
directoryEntry.getDirectory('videos', { create: true }, videoDirectoryEntry => {
// Copy video file (entry) to 'videos' directory
entry.copyTo(videoDirectoryEntry, 'copiedVideo', copiedEntry => {
// I should now have a file entry of the copied video, but I don't. I get an error.
console.log(copiedEntry);
}, err => {
console.error(err); // This is where I capture the NOT_FOUND_ERR error
});
}, onError);
}, onError);
});
}
onError(error: Error) {
console.error(error.message)
}
Any idea why the file isn't being copied? Do I need to request specific permissions to write to cordova.file.dataDirectory?
After a lot of trial and error, it turns out I needed to request the READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions for Android.
At a future date I'll check if any permissions are needed for iOS, but for now I'm happy that it's working for Android.
I have an Ionic 4 app developed using InAppBrowser. The app is, in fact, almost all purely done via InAppBrowser:
Splash Screen > URL passed to InAppBrowser > Site loads.
User logins in, clicks links and navigates through site.
Some links the user may click are PDFS (content type = application/pdf) but does not have a .pdf extension at the end of the filename.
In iOS, these load fine. In Android, the PDFs never show....
I've read this is a known workaround. I cannot use the Google Docs viewer embed workaround as the URL to the pdf files are based on being authenticated into our site to see and access the PDFs.
The other option I'm reading is to get the URL, download the file to the user's local system browser; then open it up - all of this using FileSystem, File, FileTransfer, and FileOpener. Below is my code block and output from Android Studio LOGCAT:
downloadPDF(pUrl: string) {
console.log("==== in downloadOpenPDF function ====");
if(this.platform.is('android')) {
var permissions = cordova.plugins.permissions;
permissions.hasPermission(permissions.WRITE_EXTERNAL_STORAGE , function( status ){
if ( status.hasPermission ) {
console.log("We DO have access to write to external storage");
}
else {
console.warn("We DO NOT have access to write to external storage");
permissions.requestPermission(permissions.WRITE_EXTERNAL_STORAGE, this.success, this.error);
}
});
permissions.hasPermission(permissions.READ_EXTERNAL_STORAGE , function( status ){
if ( status.hasPermission ) {
console.log("We DO have access to read to external storage");
}
else {
console.warn("We DO NOT have access to read to external storage");
permissions.requestPermission(permissions.READ_EXTERNAL_STORAGE, this.success, this.error);
}
});
}
let downloadUrl = pUrl;
console.log("downloadUrl is ================"+downloadUrl);
let path = this.file.dataDirectory;
let filepath = path+'mcfrenderPDF.pdf';
console.log("path is =================="+path);
const transfer: FileTransferObject = this.fileTransfer.create();
transfer.download(downloadUrl, filepath,true).then(entry => {
let url = entry.toUrl();
console.log("url is ================="+url);
if(this.platform.is('ios') || this.platform.is('android')) {
console.log("================ Use Document Viewer");
this.document.viewDocument(url, 'application/pdf',{});
} else {
//console.log("Device is Android = Use Google Docs");
//this.openGoogleDocsPDF(pUrl);
console.log("local path to file is: "+path+'mcfrenderPDF.podf');
this.fileOpener.open(entry.URL, 'application/pdf');
}
})
}
My output of my log is as follows:
2019-11-03 13:26:05.401 5213-5333/com.cat.fpd.mobile.mcf D/FileTransfer: Saved file: file:///data/user/0/com.cat.fpd.mobile.mcf/files/mcfrenderPDF.pdf
2019-11-03 13:26:05.401 5213-5333/com.cat.fpd.mobile.mcf E/FileTransfer: File plugin cannot represent download path
I am using this plugin for getting files
https://ionicframework.com/docs/native/file-chooser/
When I select a PDF file from Downloads folder it is giving me a URI like content://com.android.providers.downloads.documents/document/1015
But if i select another file like ZIP or PNG it resolves to a suitable path
content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Fwws.zip
content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Fopacity.png
How do I get the path from a file in the form of file://….
I have tried the following approaches with no success yet:
FilePath.resolveNativePath
and
normalizeURL
UPDATE:
Imports
import { File } from '#ionic-native/file';
import { FileChooser } from '#ionic-native/file-chooser'
import { FilePath } from '#ionic-native/file-path';
Code for file chooser:
getAndroidFile() {
this.fileChooser.open()
.then(uri => {
console.log("uri", uri);
this.file.resolveLocalFilesystemUrl(uri).then((files) => {
console.log("files", files);
}).catch((error) => { console.log("error", error) });
(<any>window).FilePath.resolveNativePath(uri, (result) => {
this.nativepath = result;
console.log("nativepath", this.nativepath);
}, (err) => {
console.log("err", err);
})
})
}
I have used it as Aaron suggested:
this.file.resolveLocalFilesystemUrl(uri).then((files)=>{
console.log("files",files);
}).catch((error) => { console.log("error", error) });
It still returns as:
filesystem: FileSystem {name: "content", root: DirectoryEntry}
fullPath: "/com.android.providers.downloads.documents/document/1015"
isDirectory: false
isFile: true
name: "1015"
nativeURL: "content://com.android.providers.downloads.documents/document/1015"
Which is the original url.
UPDATE 2:
getBase64Content(nativepath) {
let path = nativepath.substring(0, nativepath.lastIndexOf('/'));
let filename = nativepath.substring(nativepath.lastIndexOf('/'), nativepath.length);
filename = filename.replace("/", "");
console.log("path", path);
console.log("filename", filename);
this.file.readAsDataURL(path, filename)
.then(content => {
console.log('content1', content);
//this will be passed to web API
this.base64content = content;
})
.catch(err => {
console.log("err", err);
})
}
This base64 content is sent overthe to server via api and they convert it back to file.
UPDATE 3:
Sorry for late reply, really busy with another project.
Answers for Koken:
How are you testing this thing?
What command are you using for the execution?
ionic cordova run android
(I check the values by remote debugging using chrome.)
Android emulator? Android device?
Android Device. Redmi note 5 pro(MIUI 10, Android 8.1).
Also... what are the next steps after selecting the file?
This base64 content is sent over to server via api and they convert it back to file.
Hope you guys can help me. With code given. Thanks
you need resolveLocalFilesystemUrl from the FileManager Plugin
https://ionicframework.com/docs/native/file/#resolveLocalFilesystemUrl
I am attempting to open a PDF file with FileOpener2 (through ng-cordova) with the following code:
$cordovaFile.checkFile(cordova.file.dataDirectory, attachmentPath)
.then((fileEntry) => {
// success
fileEntry.getMetadata((metadata) => {
// metadata.size is in bytes
var megabyteSize = metadata.size / 1048576;
if (megabyteSize > 5) {
var path = cordova.file.dataDirectory + attachmentPath;
console.log(path); // prints: file:///data/data/com.ionicframework.enhatch146189/files/attachments/CS-353ES_CS-420ES_Eng.pdf which is correct
$cordovaFileOpener2.open(path, 'application/pdf').then(() => {
console.log("Opened!") // prints
}, (error) => {
console.log(error);
usePDFJs(); // tries to render PDF in app with PDFJs
});
} else {
usePDFJs();
}
})
}, function (error) {
// error
console.error(error);
});
What happens confuses me: it prompts me with an "open this file in Adobe Reader?" and lists the other PDF viewers, and the console prints "Opened!"
However, no matter what I open ANY pdf in, I get some sort of error such as "cannot open this PDF file".
Can anyone see something wrong with this code?
Apparently, if you use cordova.file.dataDirectory on android you can't open those files in other applications or attach them to emails. Silly mistake -- coded too fast and read too little on the documentation. Using cordova.file.externalApplicationStorageDirectory solved the issue.