On Android, I'm trying to upload the output from Cordova/Phonegap getPicture() using Google Drive API: Insert File. Is there a way to do this using the FILE_URI instead of DATA_URL (base64)?
I tried Camera.DestinationType.DATA_URL first, but it didn't return Base64 data like it was supposed to, it just returned the same thing as FILE_URI. So now I'm trying to figure out how to pass FILE_URI to Google Drive Insert File (which takes Base64). Is there a way to convert FILE_URI to Base64?
Cordova code:
navigator.camera.getPicture(onSuccess, onFail,
{ quality: 50, destinationType: Camera.DestinationType.FILE_URI });
function onSuccess(imageURI) {
var image = document.getElementById('myImage');
image.src = imageURI;
// need to do something like this:
var fileData = ConvertToBase64(imageURI);
insertFile(fileData);
}
Google Drive code:
/**
* Insert new file.
*
* #param {File} fileData File object to read data from.
* #param {Function} callback Function to call when the request is complete.
*/
function insertFile(fileData, callback) {
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var reader = new FileReader();
reader.readAsBinaryString(fileData);
reader.onload = function(e) {
var contentType = fileData.type || 'application/octet-stream';
var metadata = {
'title': fileData.fileName,
'mimeType': contentType
};
var base64Data = btoa(reader.result);
var multipartRequestBody =
delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Type: ' + contentType + '\r\n' +
'Content-Transfer-Encoding: base64\r\n' +
'\r\n' +
base64Data +
close_delim;
var request = gapi.client.request({
'path': '/upload/drive/v2/files',
'method': 'POST',
'params': {'uploadType': 'multipart'},
'headers': {
'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
},
'body': multipartRequestBody});
if (!callback) {
callback = function(file) {
console.log(file)
};
}
request.execute(callback);
}
}
I realize this is a bit old - but it now looks like you can use a FileReader in phoneGap.
I haven't tested this yet, but something like this should also work, without the canvas hack.
[EDIT - tested and revised the code below. works for me :D ]
var cfn = function(x) { console.log(x) };
var cameraOps = { quality: 50, destinationType: Camera.DestinationType.FILE_URI };
navigator.camera.getPicture(function(imagePath) {
window.resolveLocalFileSystemURL(imagePath, function(fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log("read success!!!");
console.log(evt.target.result);
};
reader.readAsDataURL(file);
}, cfn);
}, cfn);
}, cfn);
Yes you can....
Specify Destination Type as FILE_URI itself and in imagedata you will be getting the images file uri place it in a image tag and then place it inside HTML5 canvas and canvas has one method called toDataURL where you will be able to get the base64 of the corresponding image.
function onSuccess(imageData)
{
var $img = $('<img/>');
$img.attr('src', imageData);
$img.css({position: 'absolute', left: '0px', top: '-999999em', maxWidth: 'none', width: 'auto', height: 'auto'});
$img.bind('load', function()
{
var canvas = document.createElement("canvas");
canvas.width = $img.width();
canvas.height = $img.height();
var ctx = canvas.getContext('2d');
ctx.drawImage($img[0], 0, 0);
var dataUri = canvas.toDataURL('image/png');
});
$img.bind('error', function()
{
console.log('Couldnt convert photo to data URI');
});
}
Thanks to Arun for pointing me in the right direction. I ended up using this javascript function, which was based off http://jsfiddle.net/jasdeepkhalsa/L5HmW/
function getBase64Image(imgElem) {
// imgElem must be on the same server otherwise a cross-origin error will be thrown "SECURITY_ERR: DOM Exception 18"
var canvas = document.createElement("canvas");
canvas.width = imgElem.clientWidth;
canvas.height = imgElem.clientHeight;
var ctx = canvas.getContext("2d");
ctx.drawImage(imgElem, 0, 0);
var dataURL = canvas.toDataURL("image/jpeg");
dataURL = dataURL.replace(/^data:image\/(png|jpg|jpeg);base64,/, "");
return dataURL;
}
Related
I need to upload all type of files in my application and for images I need to get image height and width and for that I am using:
$scope.uploadFile = function(){
$scope.imageUploading = true;
var options = {
quality: 70,
//~ targetWidth: 1005,
//~ targetHeight: 693,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
mediaType: Camera.MediaType.PICTURE,
correctOrientation: true
};
$cordovaCamera.getPicture(options).then(function(imageData) {
imageData = imageData.split('?');
var imageURI = imageData[0];
// This function is called once an imageURI is rerturned from PhoneGap's camera or gallery function
window.resolveLocalFileSystemURL(imageURI, function(fileEntry) {
fileEntry.file(function(fileObject){
// Create a reader to read the file
var reader = new FileReader();
// Create a function to process the file once it's read
reader.onloadend = function(evt) {
// Create an image element that we will load the data into
var image = new Image()
image.onload = function(evt) {
// The image has been loaded and the data is ready
var image_width = this.width
var image_height = this.height
if(parseInt(image_width) < confArr.image_sizes.portfolio.large.w || parseInt(image_height) < confArr.image_sizes.portfolio.large.h){
Auth.toastMessage($rootScope.appMainLang.formvalidation.upload_resolution_limit.replace('%s',parseInt(confArr.image_sizes.portfolio.large.w)),'long','center');
$scope.imageUploading = false;
$ionicLoading.hide();
}else{
$scope.imageUploading = true;
$scope.jrCrop(imageURI);
}
image = null
}
// Load the read data into the image source. It's base64 data
image.src = evt.target.result
}
// Read from disk the data as base64
reader.readAsDataURL(fileObject)
}, function(){
Auth.toastMessage("There was an error reading or processing this file.","long", "center");
})
})
}, function(err) {
$scope.imageUploading = false;
$ionicLoading.hide();
// Auth.toastMessage(Auth.getlocal("timeoutText","string"),"long", "center");
});
}
when I use
mediaType: Camera.MediaType.PICTURE,
in above code it returns path of file as "file:///storage/emulated/0/...." and is working correctly.
but as I need to upload all types of files so I replaced above line with
mediaType: Camera.MediaType.ALLMEDIA
and with this path of file becomes "/storage/emulated/0/..." and then it do not enters in "window.resolveLocalFileSystemURL" function.
So is there a way to convert this later path to above mentioned like path?
Just add the file:// to the string. Like this:
var imageURI = 'file://' + imageData[0];
I am trying to upload an image (as base64 format) from phone gap application to amazon s3. The image is uploaded successfully, but it's displayed as boxes when I try to view the image in Amazon server. I used the below link for my reference.
Uploading image to S3 using phonegap, how to?
I also tried to upload the image (as imageURI) using the below link, but it throws an error Body.params is required
https://github.com/ccoenraets/phonegap-s3-upload/blob/master/client/phonegap-s3-upload/www/app.js
Please find the snippets of code,
// take picture
var options = {
quality: 75,
targetWidth: 320,
targetHeight: 320,
destinationType: 1, // 0 = base 64, 1 = imageURI
sourceType: 1, // 0:Photo Library, 1=Camera, 2=Saved Photo Album
encodingType: 0 // 0=JPG 1=PNG
};
// Take picture using device camera and retrieve image as base64-encoded string
navigator.camera.getPicture(onSuccess,onFail,options);
---------
uploading the image
var imageData = 'data:image/jpeg;base64,'+ $scope.lastPhoto;
var params = {
Key: 'test5.jpg', // for testing purpose
Body: imageData, // base64 data
ContentEncoding: 'base64',
ContentType: 'image/jpeg'
};
var fileName = "" + (new Date()).getTime() + ".jpg";
console.log ('data params' + params.Body);
bucket.upload(params, function(err, data){
$scope.hide($ionicLoading);
var result = err ? 'ERROR!' : 'UPLOADED SUCCESSFULLY...';
var alertPopup = $ionicPopup.alert({
title: 'Amazon Confirmation',
template: 'Result : ' + result
});
Can you check this link how to save canvas data to file
var data = img.replace(/^data:image/\w+;base64,/, "");
AWS.config.update({
accessKeyId : 'your-ACCESSKEYID',
secretAccessKey : 'SECRETACCESSKEY'
});
$cordovaCapture.captureVideo().then(function(videoData) {
$scope.file=videoData[0].name;
var first='file:/storage/sdcard0/DCIM/Camera/';
$cordovaFile.readAsDataURL(first,$scope.file)
.then(function (success) {
var bucket = new AWS.S3({params: { Bucket: 'your-bucket-name' }});
var params = {Key: videoData[0].name, ContentEncoding: 'base64', ContentType: 'video/mp4; charset=UTF-8' , Body: success};
bucket.upload(params).on('httpUploadProgress', function(evt) {
$scope.uploading = true;
$scope.progress = parseInt((evt.loaded * 100) / evt.total)+'%';
console.log("Uploaded :: " + $scope.progress );
$scope.$apply();
}).send(function(err, data) {
$scope.uploading = false;
/*$scope.images.push(data.Location);*/
console.log(data.Location);
$scope.$apply();
});
}, function (error) {
console.log("==========error==========");
console.log(error);
})
})
}
I have tried various solutions: $cordovaCapture, $cordovaCamera(DATA_URL can display the picture, but i want file_URI to do the same).
here is my code snippet:
$scope.addImage = function() {
var options = {limit: 1};
$cordovaCapture.captureImage(options).then(function(imageData) {
console.log(imageData);
// var jsonobj=angular.toJson(imageData);
$scope.profile.image = imageData[0];
console.log(angular.toJson(imageData));
console.log($scope.profile.image.localURL);//the path to upload
document.getElementById('myImage').src = "'"+$scope.profile.image.localURL+"'";//have already tried without the quottes
/* window.plugins.Base64.encodeFile($scope.profile.image.localURL,function(base64){ // Encode URI to Base64 needed for contacts plugin
$scope.profile.image.preview = base64;
console.log($scope.profile.image.preview);
});*/
// Success! Image data is here
}, function(err) {
});
i even tried whitelisting certainties in the module as in :
.config( [
'$compileProvider',
function( $compileProvider )
{
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|file|content|blob|cdvfile):|data:image\//);
}
])
It didn't help either. I am testing the project in both device and emulator. I even tried base64 encoding the file from the path. Nothing works as to display the recently taken picture. The path that i retrieve is like this:
cdvfile://localhost/persistent/DCIM/Camera/123123123.jpg
Instead of using file_URI to upload the image. I used data_URL,converted the image to blob and used the cordova-file-transfer plugin to upload the file to the server. In that way, i could use the base64 encoded image on the html side as well as upload at the same time.
$scope.captureImage = function() {
navigator.camera.getPicture(cameraSuccess, cameraError, {
destinationType: Camera.DestinationType.DATA_URL,
correctOrientation: true
});
}
var cameraSuccess = function(imageData) {
$scope.profileImageSource = imageData;
$scope.changeImage = function(base64Data, contentType) {
contentType = contentType || '';
var sliceSize = 512;
var byteCharacters = atob(base64Data);
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, {
type: contentType
});
}
$scope.picture = $scope.changeImage(imageData, 'image/png');
$scope.$digest();
}
HTML:
<img ng-src="data:image/gif;base64,{{profileImageSource}}">
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 am developing hybrid using phonegap 3.3. I am using camera plugin to capture image and store into photo album which working fine. Later, I have to read image file from the device storage.
I am using the following code.
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, failFS);
function gotFS(fileSystem){
fileSystem.root.getFile(imageData, {create: true}, gotFileEntry, fail);
}
function gotFileEntry(){
fileEntry.file(gotFile,fail);
}
function gotFile(file){
alert(file.getParent().fullPath);
}
I am getting error in the first line. It is giving
FileError.ENCODING_ERR
I am not sure what I am doing wrong here. After, I have to move to another directory with new name. Could anyone help me to fix.
I am using camera plugin for capture images and file plugin to read files and directory.
--Sridhar
You can try with below code to capture and copy image
var pictureSource;
var destinationType;
var FileFolder = "";
var FileName = "";
var obj_imageCapture = {
capturePicture:function(imgFolder,imgName)
{
var image = imgFolder + imgName;
FileFolder = imgFolder;
FileName = imgName;
pictureSource = navigator.camera.PictureSourceType;
destinationType = navigator.camera.DestinationType;
navigator.camera.getPicture(obj_imageCapture.onPhotoDataSuccess1, obj_imageCapture.onFail, {quality: 50, destinationType: destinationType.FILE_URI , saveToPhotoAlbum: true });
},
onPhotoDataSuccess1:function(imageData){
obj_imageCapture.createFileEntry(imageData);
},
createFileEntry:function(imageURI) {
window.resolveLocalFileSystemURI(imageURI, obj_imageCapture.copyPhoto, obj_imageCapture.onFFail);
},
copyPhoto:function(fileEntry) {
try
{
var ext = fileEntry.fullPath.substr(fileEntry.fullPath.lastIndexOf('.'));
var imageN = "";
if(FileName.indexOf('.') > 0)
{
imageN = FileName.substr(0,FileName.lastIndexOf('.')) + ext;
}
else
{
imageN = FileName + ext;
}
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSys) {
fileSys.root.getDirectory(FileFolder, {create: true, exclusive: false}, function(dir) {
fileEntry.copyTo(dir, imageN, obj_imageCapture.onCopySuccess, obj_imageCapture.onFFail);
}, obj_imageCapture.onFFail);
}, obj_imageCapture.onFFail);
}
catch(ex)
{
alert(ex.message);
}
},
onCopySuccess:function(entry) {
var smallimage = document.getElementById("myimage");
smallimage.style.display = "block";
smallimage.src = entry.fullPath + "?rand=" + Math.random();
},
onFFail:function(message)
{
alert("Error in photo : " + message.message);
}
};
Above code might helpful to you