I am trying to display an image from download folder.
imagePath: file:///storage/emulated/0/Download/sample.png
Set Image URL:
window.resolveLocalFileSystemURL(this.imagePath, function success(fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function() {
if (this.result) {
var blob = new Blob([new Uint8Array(this.result)], { type: "image/png" });
this.imgUrl = window.URL.createObjectURL(blob);
}
};
reader.readAsArrayBuffer(file);
});
}, function (err) {
this.info = 'An error was found: '+ err;
});
Display it on UI:
<img class="img-fluid" src="{{imgUrl}}" />
But code is not reaching inside onloadend callback.
Related
I am getting photos, and i want to show them (it works) and save them on my directory. I followed mixed responses from this forum and w3c to obtain this code. My problem is when im getting the fileSys directory, it goes to onError, it cant get myFolderApp directory. Monitor shows "
Failed to ensure directory:
/storage/sdcard1/Android/data/tta.kirolapp.v1/files
and
Failed to ensure directory:
/storage/sdcard1/Android/data/tta.kirolapp.v1/files
This is normal because the app default directory is
/storage/emulated/0/0Android/data/tta.kirolapp.v1/
so, i think this is the problem but i don't know how to fix it.
The code of the functions which takes the photo and manage it, is the next:
function capturePhoto() {
alert('on capturePhoto');
sessionStorage.removeItem('imagepath');
//Cogemos la imagen y la codificamos en Base64
navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50, cameraDirection: 1, saveToPhotoAlbum:true, destinationType: Camera.DestinationType.FILE_URI });
}
function onPhotoDataSuccess(imageURI) {
// Uncomment to view the base64 encoded image data
// console.log(imageData);
// Get image handle
//
var imgProfile = document.getElementById('fotoRegistro');
// Pasamos la imagen a pantalla desde imageURI
//
console.log('El url por defecto es: '+ imageURI);
imgProfile.src = imageURI;
if(sessionStorage.isprofileimage==1){
getLocation();
}
movePic(imageURI);
}
// Funcion onError
//
function onFail(message) {
alert('Failed because: ' + message);
}
function movePic(file){
window.resolveLocalFileSystemURL(file, resolveOnSuccess, resOnError);
}
//Callback function when the file system uri has been resolved
function resolveOnSuccess(entry){
console.log("Estoy en resolveOnSuccess");
var d = new Date();
var n = d.getTime();
//new file name
var identificacion= $('#idEmailReg').val();
var newFileName="foto"+identificacion+".jpg";
console.log ('El newFileName es: '+ newFileName);
var myFolderApp = "file:///storage/emulated/0/Android/data/tta.kirolapp.v1/img/";
//appConstants.localPermanentStorageFolderImg;
console.log ('El nuevo directorio es: '+ myFolderApp);
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSys) {
console.log ('Entramos en el request onSuccess');
//The folder is created if doesn't exist
fileSys.root.getDirectory( myFolderApp,
{create:true, exclusive: false},
function(directory) {
console.log('El directory es: '+ directory);
entry.moveTo(directory, newFileName, successMove, resOnError);
},
resOnError);
},
resOnError);
}
//Callback function when the file has been moved successfully - inserting the complete path
function successMove(entry) {
//Store imagepath in session for future use
// like to store it in database
sessionStorage.setItem('imagepath', entry.fullPath);
}
function resOnError(error) {
alert(error.code);
}
resOnError shows code "5", and the monitor output is the next:
I use the media plugin and take the photos with photo capturing, this is the code:
function capturePhoto(){
//var fileFolder="/storage/emulated/0/KirolApp/img/";
var fileFolder=appConstants.localPermanentStorageFolderImg();
var identificacion= $('#idEmailReg').val();
var fileName="foto"+identificacion+".jpg";
photo.takeAsync(
fileFolder,
fileName,
function() {
console.log('En capturePhoto funcion');
var urlCompleta=photo.fileFolder+photo.fileName;
console.log('URL Completa: '+ urlCompleta);
$("#fotoRegistro").attr("src","file://"+urlCompleta+"?"+(new Date()).getTime());
}
);
}
On my objects.js file:
var photo = {
fileFolder:null,
fileName:null,
takeAsync: function(fileFolder,fileName,onSuccess) {
navigator.device.capture.captureImage(
function(photoFiles) {
var tempFullPath=photoFiles[0].fullPath;
tempFullPath=tempFullPath.substring(tempFullPath.indexOf("/"));
alert("New photo in: "+tempFullPath);
fileUtilities.moveAsync(tempFullPath,fileFolder,fileName,
function() {
photo.fileFolder=fileFolder;
photo.fileName=fileName;
if(onSuccess!=false)
onSuccess();
}
);
},
function(error) {
var msgText = "Photo error: " + error.message + "(" + error.code + ")";
alert(msgText);
}
);
}
};
And fileUtilities:
var fileUtilities = {
moveAsync: function (sourceFullPath,destFolder,destName,onSuccess){
var url="file://"+sourceFullPath;
var destFile=destFolder+destName;
var ft=new FileTransfer();
ft.download(url,destFile,
function() {
window.resolveLocalFileSystemURL(url,
function(fileEntry) {
fileEntry.remove(onSuccess);
},
function(error) {
alert("Source file NOT accesible; not removed");
}
);
},
function(error) {
alert('File not copied. '+'error.code: '+error.code+'\nerror.source: '+error.source+'\nerror.target: '+error.target+'\nerror.http_status: '+error.http_status);
}
);
}
};
Thanks to M.H and G.P from UPV/EHU.
I have downloaded a PDF file as Base64 String in my phone as described in this SO Thread but I am not getting how can I render it to actual PDF so that end user can see it? I have written following code to write on the file:
var tempResponse = null;
function downloadFileOK(response){
var invocationResult = response['invocationResult'];
tempResponse = invocationResult;
var size = parseInt(invocationResult["responseHeaders"]["Content-Length"]);
window.requestFileSystem(LocalFileSystem.PERSISTENT, size, onSuccessFileHandler, onErrorFileHandler);
}
//Success
function onSuccessFileHandler(fileSystem) {
alert("inside onSuccessFileHandler START");
fileSystem.root.getFile("test2.pdf", {create: true, exclusive: false}, fileWriter, fail);
alert("inside onSuccessHandler END");
}
// Failure
function onErrorFileHandler(error) {
alert("inside onErrorFileHandler");
}
function fileWriter(entry){
alert("inside fileWriter START");
entry.createWriter(function(writer){
writer.onwriteend = function(evt) {
console.log("done written pdf :: test1.pdf");
alert("Inside onwriteend : START");
};
var temp = atob(tempResponse["text"]);
alert(temp);
writer.write(temp);
},fail);
alert("inside fileWriter END");
}
function fail(error) {
alert("inside fail");
console.log(error.code);
}
Am I doing it wrong? How can I open the PDF from my app in iOS/Android OS using javascript/jquery/cordova ?
Once you have download the base64 encoded file, you should decode it and save it to the file system so that it can be viewed later. You should not save the base in it's base64 encoded form.
You can use the utility function below to accomplish that. BTW you should take a look a the previous answer on Download PDF file from through MobileFirst Adapter since I made an update to it, it wasn't encoding the PDF properly.
var AppUtils = (function(){
// get the application directory. in this case only checking for Android and iOS
function localFilePath(filename) {
if(device.platform.toLowerCase() === 'android') {
return cordova.file.externalDataDirectory + filename;
} else if(device.platform.toLowerCase() == 'ios') {
return cordova.file.dataDirectory + filename;
}
}
// FileWritter class
function FileWritter(filename) {
this.fileName = filename;
this.filePath = localFilePath(filename);
}
// decode base64 encoded data and save it to file
FileWritter.prototype.saveBase64ToBinary = function(data, ok, fail) {
var byteData = atob(data);
var byteArray = new Array(byteData.length);
for (var i = 0; i < byteData.length; i++) {
byteArray[i] = byteData.charCodeAt(i);
}
var binaryData = (new Uint8Array(byteArray)).buffer;
this.saveFile(binaryData, ok, fail);
}
// save file to storage using cordova
FileWritter.prototype.saveFile = function(data, ok, fail) {
this.fileData = data;
var path = this.filePath.substring(0, this.filePath.lastIndexOf('/'));
var that = this;
// Write file on local system
window.resolveLocalFileSystemURL(path, function(directoryEntry) {
var options = {create: true, exclusive: false};
directoryEntry.getFile(that.fileName, options, function(file) {
file.createWriter(function(writer) {
writer.onwriteend = function(event) {
if(typeof ok === 'function') {
ok(event);
}
};
writer.write(that.fileData);
}, fail);
}, fail);
}, fail);
};
// open InApp Browser to view file
function viewFile(filename) {
var path = localFilePath(filename);
window.open(path, "_blank", "location=yes,hidden=no,closebuttoncaption=Close");
}
return {
FileWritter: FileWritter,
localFilePath: localFilePath,
viewFile: viewFile
}
})();
Your downloadFileOK should look as follow:
function downloadFileOK(response){
var pdfData = response['invocationResult']['text'];
var fileWritter = new AppUtils.FileWritter('YOUR-PDF-NAME.pdf');
fileWritter.saveBase64ToBinary(pdfData, function(r){
// file was saved
}, function(e){
// error file was not saved
});
}
If you want to open the file then you can use AppUtils.viewFile('YOUR-FILE-NAME.pdf')
I have a service upload imageto amazon s3 after i sign it with my own backend using cordova file-transfer plugin.
I call this service after taking a picture using cordova camera plugin to upload the taken picture to the s3 bucket.
The app sign correctly with my own backend but when it trigger the function upload i get the error i defined in the title.
This is the service that it call an end point in my backend to sign the file and then upload the image to amazon s3:
//Image upload Service
.factory('S3Uploader', function($q, $window, $http, $ionicPopup, API_URL) {
var signingURI = API_URL + "s3signing";
function upload(imageURI, fileName) {
document.addEventListener('deviceready', function() {
console.log('Uploading ' + fileName + ' to S3');
var deferred = $q.defer(),
ft = new FileTransfer(),
options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = fileName;
options.mimeType = "image/jpeg";
options.chunkedMode = false;
console.log('Requesting signed doc ' + signingURI);
$http.post(signingURI, {
"fileName": fileName
})
.success(function(data) {
console.log('Got signed doc: ' + JSON.stringify(data));
options.params = {
"auth": true,
"key": fileName,
"AWSAccessKeyId": data.awsKey,
"acl": "public-read",
"policy": data.policy,
"signature": data.signature,
"Content-Type": "image/jpeg"
};
ft.upload(imageURI, "https://" + data.bucket + ".s3.amazonaws.com/",
function(e) {
console.log("Upload succeeded");
console.log(JSON.stringify(e));
deferred.resolve(e);
$ionicPopup.alert({
title: 'great',
content: 'The image upload to amazon success'
});
},
function(e) {
deferred.reject(e);
$ionicPopup.alert({
title: 'Oops',
content: 'The image upload failed to amazon'
});
}, options);
})
.error(function(data, status, headers, config) {
console.log(JSON.stringify(data));
console.log(status);
$ionicPopup.alert({
title: 'Oops',
content: 'The image upload failed to sign with node'
});
});
return deferred.promise;
}, false); //device ready
}
return {
upload: upload
}
})
and here is the controller code where am calling the camera plugin and in the success of taking the picture am calling the upload function from the S3Uploader service:
.controller('newItemCtrl', function($scope, $http, $ionicPopup, $timeout, $cordovaCamera, API_URL, me, S3Uploader) {
$scope.selectPicture = function() {
document.addEventListener('deviceready', function() {
var options = {
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 300,
targetHeight: 300,
};
$cordovaCamera.getPicture(options).then(function(imageURI) {
$scope.imageSrc = imageURI;
// upload to Amazon s3 bucket
var fileName = new Date().getTime() + ".jpg";
S3Uploader.upload(imageURI, fileName).then(function() {
alert("upload to S3 successed");
});
}, function(err) {
alert(err);
});
}, false); // device ready
}; // Select picture
})
i get the erorr in this line of the controller:
S3Uploader.upload(imageURI, fileName).then(function() {
it's also important to mention am using crosswalk with my ionic app.
Your current implementation of S3Uploader.upload does not return a promise, it returns nothing. Move your declaration and return of the promise to directly inside the S3Uploader.upload function and not nested inside the document.addEventListener code.
Change your code to something like:
.factory('S3Uploader', function($q, $window, $http, $ionicPopup, API_URL) {
var signingURI = API_URL + "s3signing";
function upload(imageURI, fileName) {
var deferred = $q.defer()
document.addEventListener('deviceready', function() {
// Removed for brevity
}, false);
return deferred.promise;
}
return {
upload: upload
}
})
You are creating and returning your deferred object and it's promise from an event listener. Not the upload factory method.
Something along these lines is what you need:
.factory('S3Uploader', function($q) {
function upload() {
var deferred = $q.defer();
// listener logic
return deferred.promise;
}
return {
upload : upload
}
});
You will have problems with this, as you will want a new deferred object for each time the listener is fired. Adding a listener to a factory method to perform something seems like a bad pattern to me. The event should wrap the invocation of the factory method.
Let's say I have a API that stores some .mp3 music.
The sample link here:
https://118.69.201.34:8882/api/ApiMusic/Download?songId=2000
Now I want to write an API calling function in Angularjs to download the music to my Android devices with the song's Id number as in the link.
How can I do that? Please help :(
You can use the ngCordova FileTransfer library here: http://ngcordova.com/docs/plugins/fileTransfer/
Here's example code from that page, tweaked to your example URL:
document.addEventListener('deviceready', function () {
var fileid = "2000";
var url = "https://118.69.201.34:8882/api/ApiMusic/Download?songId=" + fileid;
var targetPath = cordova.file.documentsDirectory + fileid + ".mp3";
var trustHosts = true
var options = {};
$cordovaFileTransfer.download(url, targetPath, options, trustHosts)
.then(function(result) {
// Success!
}, function(err) {
// Error
}, function (progress) {
$timeout(function () {
$scope.downloadProgress = (progress.loaded / progress.total) * 100;
})
});
}, false);
I did it finally, here is my code. Just share for those who want to refer to this issue in the future. Thanks you guys for your answers
$scope.download = function(songId, songName) {
$ionicLoading.show({
template: 'Downloading...'
});
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
fs.root.getDirectory(
"fMusic",
{
create: true
},
function (dirEntry) {
dirEntry.getFile(
songName + ".mp3",
{
create: true,
exclusive: false
},
function gotFileEntry(fe) {
var p = fe.toURL();
fe.remove();
ft = new FileTransfer();
ft.download(
encodeURI(APIUrl + songId),
p,
function (entry) {
$ionicLoading.hide();
$scope.mp3File = entry.toURL();
},
function (error) {
$ionicLoading.hide();
alert("Download Error Source --> " + error.source);
},
false,
null
);
},
function () {
$ionicLoading.hide();
console.log("Get the file failed");
}
);
}
);
},
function () {
$ionicLoading.hide();
console.log("Request for filesystem failed");
});
}
so I am trying to use the phonegap file API to save and later load a file in the app. The save seems to be working, but reading the file throws this error:
processMessage failed: Stack: TypeError: Object #<an Object> has no method 'readAsText'
at [object Object].readAsText (file:///android_asset/www/plugins/org.apache.cordova.file/www/FileReader.js:130:33)
at file:///android_asset/www/index.html:3843:15
at file:///android_asset/www/plugins/org.apache.cordova.file/www/DirectoryEntry.js:100:9
at Object.callbackFromNative (file:///android_asset/www/phonegap.js:292:54)
at processMessage (file:///android_asset/www/phonegap.js:1029:21)
at Function.processMessages (file:///android_asset/www/phonegap.js:1063:13)
at pollOnce (file:///android_asset/www/phonegap.js:933:17)
at pollOnceFromOnlineEvent (file:///android_asset/www/phonegap.js:928:5)
No matter what I do, it always seems to throw this error. I printed out the fileReader object to the console and inspected it using weinre. It had the prototype with the readAsText() function on it, so I'm really at a loss why it's not working...
This is how I am saving the file:
var request = window.requestFileSystem;
if(typeof request != 'undefined') {
var fileSystem;
var writer;
request(LocalFileSystem.PERSISTENT, 0, function (FS) {
fileSystem = FS;
fileSystem.root.getFile("offlineData.txt", {create: true, exclusive: false}, function(fileEntry) {
fileEntry.createWriter(function(w) {
writer = w;
writer.write('This is some text yo');
}, function(e) {console.log(e);});},
function(e) {console.log(e); console.log('There was an error getting the file to write')});} ,
function(e) {\console.log('There was an error getting the file system');});}
Later in the flow, I will do something like this:
request(LocalFileSystem.PERSISTENT, 0, function(FS) {
fileSystem = FS;
fileSystem.root.getFile("offlineData.txt", null, function(_file) {
var reader = new FileReader();
reader.onloadend = function (evt) {
console.log("read success");
console.log(evt.target.result);
};
reader.onerror = function(evt) {
console.log("Error read text");
console.log("Error"+evt.error.code);
};
reader.onabort = function(evt) {
console.log("aborted read text");
console.log(evt.target.result);
};
reader.onloadstart = function(evt) {
console.log("started reading");
};
console.log(reader);
reader.readAsText(_file);
});
}, function(e) {console.log(e); console.log('There was an error getting the file.')});
In your sample, _file is a fileEntry and not file content. Can you try this :
fileSystem.root.getFile("offlineData.txt", null,
function (fileEntry) {
fileEntry.file(function (_file) {
var reader = new FileReader();
reader.onloadend = function () {
console.log("read success");
console.log(evt.target.result);
};
reader.readAsText(_file);
});
}
);