I'm using ngCordova cordova-plugin-file to try to read an image that I then want to convert to bytes. I actually want to read it as dataURL and I'm getting an error.
/* The image is located at file:///data/data/com.xxx.housekeeping/cache/tmp_Screenshot_2017-04-27-09-30-42-1816635709.png on an Android device */
$cordovaFile.readAsText(cordova.file.cache, "tmp_Screenshot_2017-04-27-09-30-421403920141.png")
.then(function (success) {
// success
console.log(success);
}, function (error) {
// error
console.log(error);
});
I tried using both readAsText and readAsDataURL but I get
Wrong type for parameter "uri" of resolveLocalFileSystemURI: Expected String, but got Undefined.
as an error. This is on an Android device.
Is there something I'm missing or doing wrong?
Should be cacheDirectory, was accessing the wrong location
$cordovaFile.readAsText(cordova.file.cacheDirectory, "tmp_Screenshot_2017-04-27-09-30-421403920141.png")
.then(function (success) {
// success
console.log(success);
}, function (error) {
// error
console.log(error);
});
Related
I'm using AngularJS v1.5.0. I'm on Chrome Version 55.0.2883.95. The error I'm seeing shows similar failure behavior to this SO post, although the error description for my situation just states Object.
I've created a plunker to demonstrate the error. Open the developer console at the plunker to see the resulting error.
Given the following service,
this.test = function() {
return $q(function(resolve, reject) {
var errorObject = {
httpStatusCode: 503,
error: {
code: 5030,
message: 'Oh no! Something went wrong, please try again'
}
};
reject(errorObject);
}).then(function successCallback(response) {
return response;
}).catch(function errorCallback(response) {
throw response;
});
};
AngularJS code generates the following error:
angular.js:13550 Object {httpStatusCode: 503, error: Object}
The AngularJS code in play is:
function consoleLog(type) {
var console = $window.console || {},
logFn = console[type] || console.log || noop,
hasApply = false;
// Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
// The reason behind this is that console.log has type "object" in IE8...
try {
hasApply = !!logFn.apply;
} catch (e) {}
if (hasApply) {
return function() {
var args = [];
forEach(arguments, function(arg) {
args.push(formatError(arg));
});
return logFn.apply(console, args); // Error thrown on this line
};
}
// we are IE which either doesn't have window.console => this is noop and we do nothing,
// or we are IE where console.log doesn't have apply so we log at least first 2 args
return function(arg1, arg2) {
logFn(arg1, arg2 == null ? '' : arg2);
};
Here's how I call the service:
var test = function() {
userService.test()
.then(function successCallback(responseObject) {
console.log('Beginning of then');
})
.catch(function errorCallback(errorResponseObject) {
console.log('Beginning of catch');
});
}
The error seems to be caused by the fact that I am handling the promise rejection, and then re-throwing it. If I don't catch and rethrow, I don't get the error. Why do I receive the error when catching and re-throwing?
Update: It appears that using the $q service to reject the caught promise rejection avoids the AngularJS error I was seeing. I'll use that approach for now, but would still be interested to know why throwing out of the promise catch generates the error.
Example code without the error:
this.test = function() {
return $q(function(resolve, reject) {
var errorObject = {
httpStatusCode: 503,
error: {
code: 5030,
message: 'Oh no! Something went wrong, please try again'
}
};
reject(errorObject);
}).then(function successCallback(response) {
return response;
}).catch(function errorCallback(response) {
return $q.reject(response);
});
};
This question has nothing to do with AngularJS and much more on how promises work (including AngularJS's $q).
Throwing in a .catch is bound to have issues. Axel has an excellent explanation
if you want a quick and dirty method to get an exception to the console(or other logging mechanisms) you can use this trick:
.catch((err) => setTimeout(() => throw err));
Or its es5 variant:
.catch(function (err) { setTimeout(function () {throw err},0)})
This will keep the error as is, and get it out of the promise chain, without changing it.
However, I think it's better to incorporate the way that Axel explains in his article.
I've found what I believe to be the answer to my question. Buried in this discussion on the AngularJS Github issues section, #gkalpak notes the following:
The only difference between them is that return $q.reject(anything) will just pass anything down the chain, while throw anything will additionally pass anything to the $exceptionHandler. Other than that, both methods work the same.
So, the issue as far as I understand it, is that the $exceptionHandler prints the exception to the console. Using $q.reject as I stated in my update and again below does avoid this behavior and is my recommended solution to avoiding the console error.
this.test = function() {
return $q(function(resolve, reject) {
var errorObject = {
httpStatusCode: 503,
error: {
code: 5030,
message: 'Oh no! Something went wrong, please try again'
}
};
reject(errorObject);
}).then(function successCallback(response) {
return response;
}).catch(function errorCallback(response) {
return $q.reject(response);
});
};
Update - Based on #Sanders-Eias answer below, it is bad practice to throw exceptions out of async functions in general. That statement further bolsters the $q.reject approach.
On app launch it checks if a certain file exists, if not then it will make an http request to get an API in json format. If the request is successfully done, then it will create a json file.
The $cordova.writeFile() logs in success handler so it must have worked (I don't know how to check if it indeed made one though).
When I close the app and relaunch it then it checks again but it goes always in the error handler doesn't exist
// On launch
$scope.checkFile('news.json');
$scope.checkFile = function(file){
$cordovaFile.checkFile(cordova.file.dataDirectory, file)
.then(function (success) {
console.log('Exists!');
}, function (error) {
console.log('Doesnt exist');
$scope.update();
});
}
//If it doesn't exist
$scope.update = function () {
// Get all news
NewsService.getAllNews().then(function (data) {
$scope.saveFile('news.json', data);
$scope.news = data;
}, function (err) {
console.log(err)
});
};
// Write file
$scope.saveFile = function (file, data) {
console.log(file) // logs news.json
console.log(data) // logs data
$cordovaFile.writeFile(cordova.file.dataDirectory, file, JSON.stringify(data), true)
.then(function (success) {
// success
console.log('Worked!');
}, function (error) {
// error
console.log('Didn't work');
});
};
Edit:
cordova.file.dataDirectory leads to:
file:///data/user/0/com.myname.appname/files/
Is this the correct path?
Edit2:
Instead of logging my own error, I logged the variable error. It says:
FileError {code: 5, message: "ENCODING_ERR"}
I am trying to figure out the type of the success object for any of the cordova file API functions? For instance, for the checkFile function it should logically be a boolean true / false reply.
Or is the then branch the positive - file exists branch and the error branch when the file does not exist?
$cordovaFile.checkFile(cordova.file.dataDirectory, "some_file.txt")
.then(function (success) {
// success
}, function (error) {
// error
});
However, it's pretty hard to tell from the documentation.
Docs states: Returns Object , and since it seems difficult to detect from a standard browser, it's some dark magic phone debugging to get familiar with the API. Any hints welcome.
After some exercises and looking at the source code, this is how I now got to understand the cordova file library with the checkFile function:
this.checkBackupExists = function(){
var deferred = $q.defer();
$cordovaFile.checkFile(cordova.file.dataDirectory, this.backupFileName)
.then(function (success) {
deferred.resolve(true);
}, function (error) {
// error
if(error.code==1) #NOT_FOUND_ERR
deferred.resolve(false);
else
deferred.reject(error);
});
return deferred.promise;
}
I believe that a successful run of 'checkFile' with result in the 'then' callback being called and and of the errors occurring here http://ngcordova.com/docs/plugins/file/#file-error-codes will result in the 'error' callback being called... with 'error' being that error code or an object containing the code.
I am making an app using Ionic framework. I have used ngcordova angular library.
I have a zip folder which we are unzipping and then reading / writing the file.
When I am updating (write operation) on any file in "non rooted" phones, we are getting NO_MODIFICATION_ALLOWED_ERR. But this works fine in a "rooted" phone.
This issue is with write operation only. It is working fine while reading any file.
Please have a look at the code.
UpdateConfiguration: function (appconfig) {
var defer = $q.defer();
$cordovaFile.checkFile(cordova.file.dataDirectory, "Stock/database/appconfig.json").then(function (success) {
$cordovaFile.writeFile(cordova.file.dataDirectory, 'Stock/database/appconfig.json', JSON.stringify(appconfig), true)
.then(function (success) {
defer.resolve(true);
}, function (err) {
alert(JSON.stringify(err));
defer.reject(false);
});
}, function (error) {
alert('Error finding app config file');
});
return defer.promise;
}
Please help.
Thanks in advance.
I am building a mobile app with Ionic/Cordova/Angular and I don't know how to get a image file by path (to be sent it to the server).
I'm using this example (http://devdactic.com/how-to-capture-and-store-images-with-ionic/ ) to get and save the image in app folder.
So I have an image name and an image path and I want to get somehow the image object to be able to convert it in base64 and send it to the server.
Any ideas ?
UPDATE:
`window.resolveLocalFileSystemURL($scope.user.image, onSuccess, onError);
function onSuccess(entry) {
/* Here: entry look like this :
"isFile":true, "isDirectory":false, "name":"myImgName1234", "fullPath": "/myImgName1234", "filesystem":"FileSystem:files>", "nativeURL":"file:///data/data/com.example.DemoApp/files/myImgName1234"
*/
$cordovaFile.readAsDataURL(cordova.file.dataDirectory, entry.name)
// I also tried : $cordovaFile.readAsDataURL(entry.nativeURL, entry.name) or $cordovaFile.readAsDataURL(entry.fullPath, entry.name)
.then(function (success) {
// success
window.alert('Succes read= '+ JSON.stringify(success));
}, function (error) {
// error
window.alert('Error read= '+ JSON.stringify(error));
});
}
function onError(error){
window.alert('error' + JSON.stringify(error));
}`
What I have also tried
Error code: 5 <- $cordovaFile.readAsDataURL(cordova.file.dataDirectory, entry.name)
Error code: 5 <- $cordovaFile.readAsDataURL(entry.nativeURL, entry.name)
Error code: 1000 <- $cordovaFile.readAsDataURL(entry.fullPath, entry.name)
Error code: 1 <- $cordovaFile.readAsDataURL(entry.name)
Is there any way to get the image Object (binary) if you know the path with cordova ? not just the image properties object (fileEntry)
use this plugin to get the file from the device: http://ngcordova.com/docs/plugins/file/
and then do what ever you want with it.
have you used the ngCordova plugin? your code should look something like this:
module.controller('MyCtrl', function($scope, $cordovaFile) {
$cordovaFile.checkFile(cordova.file.dataDirectory, "file_name.txt")
.then(function (success) {
console.log(success);
}, function (error) {
console.log(error);
});
});