I'm developing an Android application with PhoneGap, my problem is I want to take a picture and save in a specified folder, I read a lot of tutorial online but I cannot find the solution on my problem, now I take the picture and save it in the default folder.
here is my js file.
var pictureSource;
var destinationType;
document.addEventListener("deviceready",onDeviceReady,false);
function onDeviceReady() {
pictureSource=navigator.camera.PictureSourceType;
destinationType=navigator.camera.DestinationType;
}
function onPhotoDataSuccess(imageURI) {
var smallImage = document.getElementById('smallImage');
smallImage.style.display = 'block';
smallImage.src = imageURI;
movePic(imageURI);
}
function capturePhoto() {
navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50,
destinationType: destinationType.FILE_URI,
saveToPhotoAlbum: true});
}
function onFail(message) {
alert('Failed because: ' + message);
}
function movePic(file){
window.resolveLocalFileSystemURI(file, resolveOnSuccess, resOnError);
}
function resolveOnSuccess(entry){
var d = new Date();
var n = d.getTime();
var newFileName = n + ".jpg";
var myFolderApp = "Geofolder";
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSys) {
//The folder is created if doesn't exist
var direct = fileSys.root;
direct.getDirectory( myFolderApp,
{create:true, exclusive: false},
function(myFolderApp) {
entry.moveTo(myFolderApp, newFileName, successMove, resOnError);
},
resOnError);
},
resOnError);
}
function successMove(entry) {
sessionStorage.setItem('imagepath', entry.fullPath);
}
function resOnError(error) {
alert(error.code);
You have to get the directory entry.Try the following function.
function moveFile(fileUri) {
window.resolveLocalFileSystemURL(
fileUri,
function(fileEntry){
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory,
function(dirEntry) {
fileEntry.moveTo(dirEntry, "fileName.jpg", function(entry){
alert("File moved.check internal memory");
},resOnError);
},
resOnError);
},
resOnError);}
Related
I have had this issue start to appear with the device file name being created in this format:
.../DCIM/Camera/IMG_20170819_155509.jpg
But the media file data when using Cordova captureImage being returned as:
.../DCIM/Camera/1503140105277.jpg
Therefore being unable to return the image.
Here is the code:
$('body').off('click', '#add-image-inspect-attr-list').on('click', '#add-image-inspect-attr-list', function(event) {
var options = { limit: 1 };
navigator.device.capture.captureImage(inspectAttrPictureSuccess, inspectPictureError, options);
$(this).off();
});
function inspectAttrPictureSuccess(imageData) {
console.log(imageData);
var countOfImg = $('.image-display-inspect-attr-list').children().length;
var file = {
ContentType: "image/jpeg",
base64: imageData,
Data: imageData,
ID: countOfImg
};
var fileName = file.base64;
inspectShowAttrFile(fileName,0);
}
function inspectShowAttrFile(fileName, type) {
var countOfImg = $('.image-display-inspect-list').children().length;
$('.image-display-inspect-list').append('<img id="inspect-img-index-' + countOfImg + '" class="img-responsive img-thumbnail img-inspect" src="' + fileName[0].fullPath + '">');
}
The app is built with cordova 6.3.1 and the device has andriod 4.4.2
This works on some devices but not others
To get around this issue, I had to check what the last file added was to the image file location. Get the folder path, get the latest file added, then update the image data created by the captureImage function with the new file name and location data:
function inspectAttrPictureSuccess(imageData) {
var deviceImageFolder = imageData[0].localURL.replace(imageData[0].name, '');
window.resolveLocalFileSystemURL(deviceImageFolder, function (dirEntry) {
var directoryReader = dirEntry.createReader();
directoryReader.readEntries(successfile, failfile);
}, function (err) {
var errToSave = err.message;
});
function successfile(entries) {
var latestimage = entries[entries.length - 1];
imageData[0].fullPath = latestimage.fullPath
imageData[0].localURL = latestimage.nativeURL
imageData[0].name = latestimage.name
var countOfImg = $('.image-display-inspect-attr-list').children().length;
var file = {
Filename: "inspect-attr-img-" + Math.random().toString(36).substring(2, 15) + ".jpg",
ContentType: "image/jpeg",
base64: imageData,
Data: imageData,
ID: countOfImg
};
inspectImageAttrFileSendAry.push(file);
inspectImageFileSendALLAry.push(file);
console.log(inspectImageAttrFileSendAry);
console.log(inspectImageFileSendALLAry);
var fileName = file.base64;
inspectShowAttrFile(fileName, 0);
}
function failfile(error) {
console.log("Failed to list directory contents: ", error);
}
}
I have managed to setup code to write to and read from a text file.
The problem I've run into is when I try to read the file after writing it.
It returns a null value.
I am assuming this is due to the write not being complete when the read starts.
How do I make the read wait for the write.
MyFile Class
MyFile = function() {
};
MyFile.prototype.readFile = function(fileDir, fileName) {
window.resolveLocalFileSystemURL(fileDir, function(dir) {
dir.getFile(fileName, {create: true}, function(fileEntry) {
fileEntry.file(function(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");
window.localStorage.setItem(file.name + "Read", evt.target.result);
console.log(evt.target.result);
};
reader.onloadend = function(evt) {
console.log("Read " + file.name + " Ending");
};
reader.readAsText(file);
}, fail);
}, fail);
}, fail);
var strText = window.localStorage.getItem(fileName + "Read");
console.log(strText);
window.localStorage.removeItem(fileName + "Read");
return strText;
};
MyFile.prototype.overWriteFile = function(fileDir, fileName, strText) {
window.resolveLocalFileSystemURL(fileDir, function(dir) {
dir.getFile(fileName, {create: true}, function(file) {
if (!file) {
return;
} else {
console.log("Overwrite File Name: " + file.name);
}
file.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(evt) {
if (fileWriter.length === 0) {
//fileWriter has been reset, write file
fileWriter.write(strText);
} else {
//file has been overwritten with blob
//use callback or resolve promise
console.log("Write " + file.name + " Success");
console.log(strText);
}
};
fileWriter.truncate(0);
}, fail);
});
});
};
Calling Write and Read
var myf = new MyFile();
myf.overWriteFile("Directory", "test.txt","Test.txt Contents");
console.log(myf.readFile("Directory", "test.txt"));
If you dont mind jQuery you can try using a custom event that you fire when the file is done writing.
MyFile.prototype.overWriteFile = function(fileDir, fileName, strText) {
//added self var to be accessed from within createWriter finished section
var self = this
window.resolveLocalFileSystemURL(fileDir, function(dir) {
dir.getFile(fileName, {create: true}, function(file) {
if (!file) {
return;
} else {
console.log("Overwrite File Name: " + file.name);
}
file.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(evt) {
if (fileWriter.length === 0) {
//fileWriter has been reset, write file
fileWriter.write(strText);
} else {
//file has been overwritten with blob
//use callback or resolve promise
//triggers the finishedMyFileWrite on the MyFile instance
jQuery(self).tigger('finishedMyFileWrite');
console.log("Write " + file.name + " Success");
console.log(strText);
}
};
fileWriter.truncate(0);
}, fail);
});
});
};
var myf = new MyFile();
jQuery(myf).on('finishedMyFileWrite', function finishedWrite(){
console.log(this.readFile("Directory", "test.txt"));
});
myf.overWriteFile("Directory", "test.txt","Test.txt Contents");
I added a self variable to allow the custom event to target the specific instance of MyFile, then I trigger an event called finishedMyFileWrite after the file has written. The myf object is set to listen for this callback before writing. I am not able to test this as I dont have a cordova emulator, but the theory should work.
Within my Cordova app, I am downloading arbitrary files like images or video files. This is done with the Cordova file-transfer plugin and the "Range" Header, because I need to download the files in parts.
My Problem is, that I want to merge back the several small "Byte"-Files back together into the original file they once where to use that file. Every time I'm trying to read the resulting parts as binaryString via the FileReader and write them together in a new file, that file ends up a lot larger than the parts of the original file altogther and the resulting file is unusable.
Any help is appreciated.
Here is my code until now (long and ugly):
document.addEventListener('deviceready', deviceready, false);
var App;
var finishedFileUrl = "";
var async = {
sequence: function(items, callback) {
var def = $.Deferred(),
deferrers = [$.Deferred()];
for(var i = 0; i < items.length; i++) {
(function (n) {
deferrers[n + 1] = $.Deferred();
deferrers[n].always(function() {
callback(items[n], deferrers[n + 1]);
});
})(i);
}
deferrers[items.length].always(function() {
def.resolve();
});
deferrers[0].resolve();
return def.promise();
}
}
var aSmallImageArray = [
'' // Put URL to JPG accessible with Range Header Request here
];
var aByteSizeImageArray = [];
function formatDownloadArray(fileSize) {
for(var j = 1000; j <= fileSize; j += 1000) {
aByteSizeImageArray.push(j);
}
aByteSizeImageArray.push(j);
}
function deviceready() {
console.log('dv ready');
function registerHandlers() {
App = new DownloadApp();
formatDownloadArray(XXXXX); // XXXXX should be size of JPG in bytes
document.getElementById("startDl").onclick = function() {
var that = this;
console.log("load button clicked");
var folderName = "testimagefolder";
// sequence call
async.sequence(aByteSizeImageArray, function(currentBytes, iter) {
var filePath = aSmallImageArray[0];
var fileName = aSmallImageArray[0].substr(52,99) + currentBytes;
console.log(filePath);
console.log(fileName);
console.log("Starting with: " + fileName);
var uri = encodeURI(filePath);
var folderName = "testimagefolder";
document.getElementById("statusPlace").innerHTML = "<br/>Loading: " + uri;
App.load(currentBytes, uri, folderName, fileName,
function progress (percentage) {
document.getElementById("statusPlace").innerHTML = "<br/>" + percentage + "%";
},
function success (entry) {
console.log("Entry: " + entry);
document.getElementById("statusPlace").innerHTML = "<br/>Image saved to: " + App.filedir;
console.log("DownloadApp.filedir: " + App.filedir);
iter.resolve();
},
function error () {
document.getElementById("statusPlace").innerHTML = "<br/>Failed load image: " + uri;
iter.resolve();
}
);
}).then(function afterAsync () {
console.log("ASYNC DONE");
var ohNoItFailed = function ohNoItFailed (exeperro) {
console.log(exeperro);
}
// now we merge the fileparts into one file to show it
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (FileSystem) {
FileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, function itSuccessed (Directory) {
Directory.getFile(aSmallImageArray[0].substr(52,99), {create: true, exclusive: false}, function itSuccessedAgain (fileEntry) {
finishedFileUrl = fileEntry.toURL();
var directoryReader = Directory.createReader();
var allFiles = directoryReader.readEntries(function succesReadDir (fileEntries) {
async.sequence(fileEntries, function(currentFile, iterThis) {
currentFile.file(function (theActualFile) {
var myFileReader = new FileReader();
myFileReader.onload = function (content) {
console.log('FileReader onload event fired!');
console.log('File Content should be: ' + content.target.result);
fileEntry.createWriter(
function mergeImage (writer) {
writer.onwrite = function (evnt) {
console.log("Writing successful!");
iterThis.resolve();
}
writer.seek(writer.length);
writer.write(content.target.result);
}, ohNoItFailed);
};
myFileReader.readAsBinaryString(theActualFile);
}, ohNoItFailed);
}).then(function afterAsyncTwo () {
console.log("NOW THE IMAGE SHOULD BE TAKEN FROM THIS PATH: " + finishedFileUrl);
//window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (FileSystem) {
//FileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, function itSuccessed (Directory) {
//Directory.getFile(aSmallImageArray[0].substr(52,99), {create: true, exclusive: false}, function itSuccessedAgain (fileEntry) {
//fileEntry.createWriter(
document.getElementById("image_here").src = finishedFileUrl;
});
}, ohNoItFailed);
}, ohNoItFailed);
}, ohNoItFailed);
}, ohNoItFailed);
});
};
}
registerHandlers();
}
var DownloadApp = function() {}
DownloadApp.prototype = {
filedir: "",
load: function(currentBytes, uri, folderName, fileName, progress, success, fail) {
var that = this;
that.progress = progress;
that.success = success;
that.fail = fail;
filePath = "";
that.getFilesystem(
function(fileSystem) {
console.log("GotFS");
that.getFolder(fileSystem, folderName, function(folder) {
filePath = folder.toURL() + fileName;
console.log("FILEPATH: " + filePath);
console.log("URI: " + uri);
that.transferFile(currentBytes, uri, filePath, progress, success, fail);
}, function(error) {
console.log("Failed to get folder: " + error.code);
typeof that.fail === 'function' && that.fail(error);
});
},
function(error) {
console.log("Failed to get filesystem: " + error.code);
typeof that.fail === 'function' && that.fail(error);
}
);
},
getFilesystem: function (success, fail) {
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, success, fail);
},
getFolder: function (fileSystem, folderName, success, fail) {
fileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, success, fail)
},
transferFile: function (currentBytes, uri, filePath, progress, success, fail) {
var that = this;
that.progress = progress;
that.success = success;
that.fail = fail;
console.log("here we go");
console.log("filePath before Request: " + filePath);
var previousBytes = currentBytes - 1000;
var transfer = new FileTransfer();
transfer.onprogress = function(progressEvent) {
if (progressEvent.lengthComputable) {
var perc = Math.floor(progressEvent.loaded / progressEvent.total * 100);
typeof that.progress === 'function' && that.progress(perc); // progression on scale 0..100 (percentage) as number
} else {
}
};
transfer.download(
uri,
filePath,
function success (entry) {
console.log("File saved to: " + entry.toURL());
typeof that.success === 'function' && that.success(entry);
},
function errorProblem(error) {
console.log("An error has occurred: Code = " + error.code);
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("download error code " + error.code);
typeof that.fail === 'function' && that.fail(error);
},
true,
{
headers: {
"Range": "bytes=" + previousBytes + "-" + currentBytes
}
}
);
}
}
async code by stackoverflow-user: Paul Facklam
-> Thanks a lot!
you can build a blob from other blobs, like the ones you use FileReader on now. (File()s are Blobs)
// put three blobs into a fourth:
var b=new Blob([new Blob(["hello"]), new Blob([" "]), new Blob(["world"])]);
// verify the blob has the data we expect:
var fr=new FileReader();
fr.onload=function(){alert(this.result);};
fr.readAsBinaryString(b); // shows: "hello world"
the binaryString flavor is used here to show how these low-order strings stack up, but the actual new blob instance should have all the orig (arbitrary) bytes from the original blobs, even if they aren't composed of simple strings...
Using readAsArrayBuffer() instead of readAsBinaryString() did the trick!
So instead of:
myFileReader.readAsBinaryString(theActualFile);
I did:
myFileReader.readAsBinaryArray(theActualFile);
And the resulting image file is usable.
I'm trying to upload a file from a cordova app to a node server. I am getting this exception in the server side
Cannot read property 'file' of undefined
i'm newbie in javascript and i need help thanks
this is the client code
<script type="text/javascript" charset="utf-8">
// Wait for device API libraries to load
//
document.addEventListener("deviceready", onDeviceReady, false);
// device APIs are available
//
function onDeviceReady() {
// Retrieve image file location from specified source
navigator.camera.getPicture(
uploadPhoto,
function(message) { alert('get picture failed'); },
{
quality : 50,
destinationType : navigator.camera.DestinationType.FILE_URI,
sourceType : navigator.camera.PictureSourceType.PHOTOLIBRARY
}
);
}
function uploadPhoto(imageURI) {
var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType="image/jpeg";
var params = {};
params.value1 = "test";
params.value2 = "param";
options.params = params;
var ft = new FileTransfer();
ft.upload(imageURI, encodeURI("http://10.20.160.38:3000/images"), win, fail, options);
}
function win(r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
}
function fail(error) {
alert("An error has occurred: Code = " + error.code);
console.log("upload error source " + error.source);
console.log("upload error target " + error.target);
}
</script>
and this is the server code
(function () {
var serverURL = "http://192.168.1.4:3000", // IMPORTANT: This URL needs to be accessible from your phone for testing.
$scroller = $('.scroller'),
// Get List of images from server
getFeed = function () {
$scroller.empty();
$.ajax({url: serverURL + "/images", dataType: "json", type: "GET"}).done(function (data) {
var l = data.length;
for (var i = 0; i < l; i++) {
$scroller.append('<img src="' + serverURL + '/' + data[i].fileName + '"/>');
}
});
},
// Upload image to server
upload = function (imageURI) {
var ft = new FileTransfer(),
options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = 'filename.jpg'; // We will use the name auto-generated by Node at the server side.
options.mimeType = "image/jpeg";
options.chunkedMode = false;
options.params = { // Whatever you populate options.params with, will be available in req.body at the server-side.
"description": "Uploaded from my phone"
};
ft.upload(imageURI, serverURL + "/images",
function (e) {
getFeed();
},
function (e) {
alert("Upload failed");
}, options);
},
// Take a picture using the camera or select one from the library
takePicture = function (e) {
var options = {
quality: 45,
targetWidth: 1000,
targetHeight: 1000,
destinationType: Camera.DestinationType.FILE_URI,
encodingType: Camera.EncodingType.JPEG,
sourceType: Camera.PictureSourceType.CAMERA
};
navigator.camera.getPicture(
function (imageURI) {
alert(imageURI);
upload(imageURI);
},
function (message) {
// We typically get here because the use canceled the photo operation. Fail silently.
}, options);
return false;
};
$('.camera-btn').on('click', takePicture);
getFeed();
}());
I would like to ask you here about some problem.
I am using Phonegap to build an application that can take photo and then show the picture in a canvas.After drawimage in the canvas, I use a method to convert canvas to image file. But I have a problem related to writing file as image file to SD Card in Android,i.e, I cannot read the image file that was created in SD Card (image is invalid).
Here is my code:
var picture = "";
function takePhoto() {
navigator.camera.getPicture(onCameraSuccess,
onCameraError,{
quality : 50,
destinationType : Camera.DestinationType.FILE_URI
//saveToPhotoAlbum: true
});
}
function onCameraSuccess(imageURL) {
var canvas = document.getElementById('myCanvas');
var ctx=canvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 0, 0,220,180);
};
imageObj.src=imageURL;
picture = imageURL;
}
function onCameraError(e) {
console.log(e);
navigator.notification.alert("onCameraError: " + e +" (" + e.code + ")");
}
function storePhoto() {
movePic(pictures);
}
function movePic(){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
}
function gotFS(fileSystem) {
fileSystem.root.getFile("test.PNG", {create: true, exclusive: false}, gotFileEntry, fail);
}
function gotFileEntry(fileEntry) {
fileEntry.createWriter(gotFileWriter, fail);
}
function gotFileWriter(writer) {
var c = document.getElementById('myCanvas');
var img_from_canvas=c.toDataURL("image/png"); // base64 encoded
var pic = img_from_canvas.split("base64,");
var pictures =window.atob(pic[1]); // decode base64
writer.write(pictures);
alert("Your picture was successfully stored !")
}
function fail(error) {
console.log(error.code);
}
I am appreciated for your helps and suggestion.
are you doing any kind of editing on image after capturing by canvas ?
if not then you can try this code to move file to root folder
var fs;
function movePic(){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
}
function gotFS(fileSystem) {
fs = fileSystem;
window.resolveLocalFileSystemURI(picture, gotFileEntry, fail);
}
function gotFileEntry(fileEntry) {
fileEntry.moveTo( fs.root,fileEntry.name, success, fail);
}
function fail(error) {
console.log(error.code);
}
You have problem with writer.write(pictures);
Try this instead
var buffer = new ArrayBuffer(pictures.length);
var array = new Uint8Array(buffer);
for (var i = 0; i < pictures.length; i++) {
array[i] = pictures.charCodeAt(i);
}
writer.write(buffer);
It work for me.