How to read object written through cordova file plugin? - javascript

I read on Cordova's documentation for android platform a code snipped and tried to use it for writing a JS object on a text file. The object gets successfully written but when I read it with FileReader API I can't get output as expected.
function writeFile(fileEntry, dataObj, isAppend) {
// Create a FileWriter object for our FileEntry (log.txt).
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function() {
console.log("Successful file read...");
readFile(fileEntry);
};
fileWriter.onerror = function (e) {
console.log("Failed file read: " + e.toString());
};
// If we are appending data to file, go to the end of the file.
if (isAppend) {
try {
fileWriter.seek(fileWriter.length);
}
catch (e) {
console.log("file doesn't exist!");
}
}
fileWriter.write(dataObj);
});
}
function readFile(fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function() {
console.log("Successful file read: " + this.result);
//displayFileData(fileEntry.fullPath + ": " + this.result);
};
reader.onload = function(){
k=reader.readAsText(file);
};
reader.readAsText(file);
},onErrorLoadFs );
}
Format of object I want to read :
function sub(name,absent,present){
this.name=name;
this.absent=absent;
this.present=present;
}
var S = new sub('Physics',1,3);
var k= new sub();
What exactly I want to do :
I am writing an object S on the file which appears like this when opened
{"name":"Physics","absent":1, "present" : 3}
Now after reading the file (which in my case is filetoAppend.txt) I want to assign these values to another object k so that when I run k.name, Physics is shown as output.
console output
k
"{"name":"Physics","absent":1,"present":3}"
k.name
undefined

With the Cordova File Plugin, there are two essential pieces of information to remember:
1.Like all Cordova plugins, you have to wait for the deviceready event before you try anything,
2.Then, Use window.resolveLocalFileSystemURL(<path>, <successHandler>, <errorHandler>)
window.resolveLocalFileSystemURL() returns a FileEntry or DirectoryEntry instance (depending on whether you gave a file or a directory as path as its first parameter), which you can then work with.
WRITING TO A FILE
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() {
function writeToFile(fileName, data) {
data = JSON.stringify(data, null, '\t');
window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function (directoryEntry) {
directoryEntry.getFile(fileName, { create: true }, function (fileEntry) {
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function (e) {
// for real-world usage, you might consider passing a success callback
console.log('Write of file "' + fileName + '"" completed.');
};
fileWriter.onerror = function (e) {
// you could hook this up with our global error handler, or pass in an error callback
console.log('Write failed: ' + e.toString());
};
var blob = new Blob([data], { type: 'text/plain' });
fileWriter.write(blob);
}, errorHandler.bind(null, fileName));
}, errorHandler.bind(null, fileName));
}, errorHandler.bind(null, fileName));
}
writeToFile('example.json', { foo: 'bar' });
}
WRITING FROM FILE
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() {
function readFromFile(fileName, cb) {
var pathToFile = cordova.file.dataDirectory + fileName;
window.resolveLocalFileSystemURL(pathToFile, function (fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function (e) {
cb(JSON.parse(this.result));
};
reader.readAsText(file);
}, errorHandler.bind(null, fileName));
}, errorHandler.bind(null, fileName));
}
var fileData;
readFromFile('data.json', function (data) {
fileData = data;
});
}
cb is the callback function that you need to pass when calling this function
For full reference use:https://www.neontribe.co.uk/cordova-file-plugin-examples/
Updated based on your updated Question
In reader.onloadend you can get the result of the file and assign to your output object k or can call callback function incase.
reader.onloadend = function (e) {
//cb(JSON.parse(this.result));
var k=JSON.parse(this.result);
console.log(k.name + ", " + k.absent+ ", " + k.present);
};
var k = JSON.parse('{"name":"Physics","absent":1, "present" : 3}');
console.log(k.name + ", " + k.absent + ", " + k.present);

Related

HTML5 Read File Returns Results before File is Read

I am trying to read a text file and return the results.
So far I am able to read the file, but when I try to return the results the results are returned before the file read is done.
How do I force the function to wait for the results?
I figure its something to do with a callback but don't know how to implement it.
MyFile.prototype.readFile = function(fileDir, fileName) {
var strText = "";
window.resolveLocalFileSystemURL(fileDir, gotDir, fail);
function gotDir(dir) {
dir.getFile(fileName, {create: true}, gotFile, fail);
}
function gotFile(fileEntry) {
fileEntry.file(gotRead, fail);
}
function gotRead(file) {
var reader = new FileReader();
reader.onerror = function(evt) {
console.log("Reading " + file.name + " Failed");
};
reader.onloadstart = function(evt) {
console.log("Read " + file.name + " Starting");
};
reader.onload = function(evt) {
console.log("Read " + file.name + " Successful");
};
reader.onloadend = function(evt) {
console.log("Read " + file.name + " Ending");
endRead(evt.target.result);
};
reader.onprogress = function(evt) {
console.log(evt.loaded + " of " + evt.total);
};
reader.readAsText(file);
}
function endRead(value) {
strText = value;
}
//returns null value before file read finishes
return strText;
};
The FileSystem api is asynchronous, meaning you have to pass a callback to your readFile method which will get called when the file is read. It's not possible to synchronously do it, see this.
You can change your signature to this:
MyFile.prototype.readFile = function(fileDir, fileName, endRead) {
And remove the following lines
function endRead(value) {
strText = value;
}
//returns null value before file read finishes
return strText;
Now, you can pass a function as the third argument to readFile method and access the file contents using the first parameter of that function.

Cordova Move File using the file url

How can I move a file using the URL I get from the Camera?
neither successCallback nor errorCallback is called by the function moveTo. Can anyone tell me what I am doing wrong and what a possible solution looks like?
function successCallback(entry) {
console.log("New Path: " + entry.fullPath);
alert("Success. New Path: " + entry.fullPath);
}
function errorCallback(error) {
console.log("Error:" + error.code)
alert(error.code);
}
// fileUri = file:///emu/0/android/cache/something.jpg
function moveFile(fileUri) {
newFileUri = cordova.file.dataDirectory + "images/";
oldFileUri = fileUri;
fileExt = "." + oldFileUri.split('.').pop();
newFileName = guid("car") + fileExt;
// move the file to a new directory and rename it
fileUri.moveTo(cordova.file.dataDirectory, newFileName, successCallback, errorCallback);
}
I am using Cordova version 4.1.2 Also installed the Cordova File Plugin
You're trying to call the function moveTo on a String.
moveTO is not a function of String but of fileEntry. So first thing you need to do is get a fileEntry from your URI.
For that you'll call window.resolveLocalFileSystemURL :
function moveFile(fileUri) {
window.resolveLocalFileSystemURL(
fileUri,
function(fileEntry){
newFileUri = cordova.file.dataDirectory + "images/";
oldFileUri = fileUri;
fileExt = "." + oldFileUri.split('.').pop();
newFileName = guid("car") + fileExt;
window.resolveLocalFileSystemURL(newFileUri,
function(dirEntry) {
// move the file to a new directory and rename it
fileEntry.moveTo(dirEntry, newFileName, successCallback, errorCallback);
},
errorCallback);
},
errorCallback);
}

Save image file in sdcard in firefox OS

I am trying to save an image in sdcard. I am following this documentation.
$('.btnSave').on('click', function () {
var imageRawData = canvas.toDataURL("image/png") ;
var sdcard = navigator.getDeviceStorage("sdcard");
var file = new Blob([imageRawData], { type: "image/png" });
var request = sdcard.addNamed(file, "FilertedImage.png");
request.onsuccess = function () {
var name = this.result;
console.log('File "' + name + '" successfully wrote on the sdcard storage area');
}
request.onerror = function (e) {
console.log('Unable to write the file: ' + e.target.error.name);
}
});
In the documentation I found that "pictures only accepts Blob with a valid image mime type". So how can I convert imageRawData to valid image mime type using javascript.
I have done it like the following - Saves and then shares:
function saveAndSend(blob) {
var sdcard = navigator.getDeviceStorage("sdcard");
var request = sdcard.addNamed(blob, "test/mycanvas.png");
//could just share the blob instead of saving
request.onsuccess = function () {
var sharingImage = new MozActivity({
name: "share",
data: {
type: "image/*",
number: 1,
blobs: [blob],
filenames: ["mycanvas.png"],
filepaths: ["test/mycanvas.png"]
}
});
}
// An error could occur if a file with the same name already exist
request.onerror = function () {
alert('Unable to write the file: ' + this.error.name);
}
}
var cnv = document.getElementById('myCanvas');
cnv.toBlob(function (blob) {
//var sdcard = navigator.getDeviceStorage("pictures");
var sdcard = navigator.getDeviceStorage("sdcard");
var request = sdcard.delete("test/mycanvas.png");
//try to delete in case it exists
request.onsuccess = function () {
saveAndSend(blob);
}
request.onerror = function () {
saveAndSend(blob);
}
});
Your app also need to make sure that it has the appropriate device storage permissions.
See: https://github.com/mozilla-b2g/gaia/blob/master/dev_apps/ds-test/manifest.webapp#L13 for an example. ds-test is a test app I wrote for testing things in device storage.

generic async callback function

this.init = function (onupgradeneeded, onsuccess) {
var openRequest = indexedDB.open(dbName);
openRequest.onupgradeneeded = function (e) {
db = e.target.result;
if (!db.objectStoreNames.contains(objectStoreName)) {
console.log('Creating the ' + objectStoreName + ' objectstore');
db.createObjectStore(objectStoreName, { keyPath: "id", autoIncrement: true });
}
};
openRequest.onsuccess = function (e) {
db = e.target.result;
db.onerror = function (event) {
// Generic error handler for all errors targeted at this database requests
console.log("Database error: " + event.target.errorCode);
};
};
};
Called by:
var idb = new Demo.IndexedDB();
idb.init();
When the init function runs, it will either end up in openRequest.onupgradeneeded or openRequest.onsuccess.
What i would like to know is if its possible to create a generic callback function that gets called in both function. So regardless of which of the two functions that runs i can know when theyre done by using
idb.init(function(){
//onupgradeneeded or onsuccess completed
});
Hope you get the idea, otherwise ill elaborate.
Thanks
Just pass in one callback function and call that one single callback in both cases:
this.init = function (onFinish) {
var openRequest = indexedDB.open(dbName);
openRequest.onupgradeneeded = function (e) {
db = e.target.result;
if (!db.objectStoreNames.contains(objectStoreName)) {
console.log('Creating the ' + objectStoreName + ' objectstore');
db.createObjectStore(objectStoreName, { keyPath: "id", autoIncrement: true });
}
onFinish();
};
openRequest.onsuccess = function (e) {
db = e.target.result;
db.onerror = function (event) {
// Generic error handler for all errors targeted at this database requests
console.log("Database error: " + event.target.errorCode);
};
onFinish();
};
};

How to create a directory and file in that directory using phonegap file api?

I am using phonegap file api to create a directory and create a file in the directory created. The directory is getting created, but the file is not getting created in the directory.
The code I am using is:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
}
function gotFS(fileSystem) {
var dataDir = fileSystem.root.getDirectory("data", {create: true});
var file = dataDir.getFile("lockfile.txt", {create: true, exclusive: true});
}
The directory data is created but lockfile.txt is not getting created.
You need to call the code in an async manner:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
}
function gotFS(fileSystem) {
fileSystem.root.getDirectory("data", {create: true}, gotDir);
}
function gotDir(dirEntry) {
dirEntry.getFile("lockfile.txt", {create: true, exclusive: true}, gotFile);
}
function gotFile(fileEntry) {
// Do something with fileEntry here
}
Is this work?
var file = fileSystem.root.getFile("data" + "lockfile.txt", {create: true, exclusive: true});
Download file from the url to your device using phonegap
It is working 3.0 and up to for iOS and android
var folderName = 'xyz';
var fileName;
function downloadFile(URL) {
//step to request a file system
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, fileSystemSuccess, fileSystemFail);
function fileSystemSuccess(fileSystem) {
var download_link = encodeURI(URL);
fileName = download_link.substr(download_link.lastIndexOf('/') + 1); //Get filename of URL
var directoryEntry = fileSystem.root; // to get root path of directory
directoryEntry.getDirectory(folderName, {
create: true,
exclusive: false
}, onDirectorySuccess, onDirectoryFail); // creating folder in sdcard
var rootdir = fileSystem.root;
var fp = fileSystem.root.toNativeURL(); // Returns Fullpath of local directory
fp = fp + "/" + folderName + "/" + fileName; // fullpath and name of the file which we want to give
// download function call
filetransfer(download_link, fp);
}
function onDirectorySuccess(parent) {
// Directory created successfuly
}
function onDirectoryFail(error) {
//Error while creating directory
alert("Unable to create new directory: " + error.code);
}
function fileSystemFail(evt) {
//Unable to access file system
alert(evt.target.error.code);
}
}
function filetransfer(download_link, fp) {
var fileTransfer = new FileTransfer();
// File download function with URL and local path
fileTransfer.download(download_link, fp,
function(entry) {
alert("download complete: " + entry.fullPath);
},
function(error) {
//Download abort errors or download failed errors
alert("download error source " + error.source);
}
);
}
function download(URL, fileName){
var folderName = 'xyz';
var uri = encodeURI(URL);
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
function (fileSystem) {
var directoryEntry = fileSystem.root; // to get root path of directory
directoryEntry.getDirectory(folderName, {
create: true,
exclusive: false
}, onDirectorySuccess, onDirectoryFail);
var filename = fileSystem.root.toURL() + folderName + "/" + uri.substr(uri.lastIndexOf("/") + 1);
var fileTransfer = new FileTransfer();
fileTransfer.download(uri, filename,
function(entry) { // download success
var path = entry.toURL(); //**THIS IS WHAT I NEED**
window.plugins.toast.showLongBottom("Download Completed: " + entry.fullPath, function (a) {
}, function (b) {
});
},
function(error) {
console.log("error")
} // irrelevant download error
);`enter code here`
},
function(error) {
console.log("error2")
} // irrelevant request fileSystem error
);
function onDirectorySuccess(parent) {
// Directory created successfuly
console.log("Directory created successfuly: " + JSON.stringify(parent));
var fp = (parent.nativeURL) + fileName;
filetransfer(download_link, fp);
}
function onDirectoryFail(error) {
//Error while creating directory
alert("Unable to create new directory: " + error.code);
}
}

Categories

Resources