Ionic app image upload from camera / photo library - ios

I'm working on a ionic chat app where the user can upload a photo as part of their message. I'm looking for a way to upload the image to my webhost server so I can retrieve it later via a URL.
The problem is that I'm not able to get it to upload to my web server.
I'm using these two plugins:
org.apache.cordova.file-transfer
cordova-plugin-camera
When I run the app in xcode simulator and select a picture from the device photolibrary, the console gives me the following messages:
File Transfer Finished with response code 200
void SendDelegateMessage(NSInvocation *): delegate (webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:) failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode>
SUCCESS: ""
This is the code I currently use:
app.controller('HomeController', function($rootScope, $scope, $cordovaCamera, $ionicActionSheet, $cordovaFileTransfer){ ...
// open PhotoLibrary
$scope.openPhotoLibrary = function() {
var options = {
quality: 100,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
$cordovaCamera.getPicture(options).then(function(imageData) {
//console.log(imageData);
//console.log(options);
var url = "http://mydomein.com/upload.php";
//target path may be local or url
var targetPath = imageData;
var filename = targetPath.split("/").pop();
var options = {
fileKey: "file",
fileName: filename,
chunkedMode: false,
mimeType: "image/jpg"
};
$cordovaFileTransfer.upload(url, targetPath, options).then(function(result) {
console.log("SUCCESS: " + JSON.stringify(result.response));
alert("success");
alert(JSON.stringify(result.response));
}, function(err) {
console.log("ERROR: " + JSON.stringify(err));
alert(JSON.stringify(err));
}, function (progress) {
// constant progress updates
$timeout(function () {
$scope.downloadProgress = (progress.loaded / progress.total) * 100;
})
});
}, function(err) {
// error
console.log(err);
});
}
This is my upload.php file:
<?php
// move_uploaded_file($_FILES["file"]["tmp_name"], $cwd . '/files/images/');
move_uploaded_file($_FILES["file"]["tmp_name"], "/files/images");
?>

After some digging around and lot's of trying I finally got it working.
This is the code I came up with:
// open PhotoLibrary
$scope.openPhotoLibrary = function() {
var options = {
quality: 50,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
$cordovaCamera.getPicture(options).then(function(imageData) {
//console.log(imageData);
//console.log(options);
var image = document.getElementById('tempImage');
image.src = imageData;
var server = "http://yourdomain.com/upload.php",
filePath = imageData;
var date = new Date();
var options = {
fileKey: "file",
fileName: imageData.substr(imageData.lastIndexOf('/') + 1),
chunkedMode: false,
mimeType: "image/jpg"
};
$cordovaFileTransfer.upload(server, filePath, options).then(function(result) {
console.log("SUCCESS: " + JSON.stringify(result.response));
console.log('Result_' + result.response[0] + '_ending');
alert("success");
alert(JSON.stringify(result.response));
}, function(err) {
console.log("ERROR: " + JSON.stringify(err));
//alert(JSON.stringify(err));
}, function (progress) {
// constant progress updates
});
}, function(err) {
// error
console.log(err);
});
}
And the code in upload.php on the domain server:
<?php
// if you want to find the root path of a folder use the line of code below:
//echo $_SERVER['DOCUMENT_ROOT']
if ($_FILES["file"]["error"] > 0){
echo "Error Code: " . $_FILES["file"]["error"] . "<br />";
}
else
{
echo "Uploaded file: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kilobytes<br />";
if (file_exists("/files/".$_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. No joke-- this error is almost <i><b>impossible</b></i> to get. Try again, I bet 1 million dollars it won't ever happen again.";
}
else
{
move_uploaded_file($_FILES["file"]["tmp_name"],"/var/www/vhosts/yourdomain.com/subdomains/domainname/httpdocs/foldername/images/".$_FILES["file"]["name"]);
echo "Done";
}
}
?>

the app I am building for a company had the same issue, what we did is we just posted the image to our server as a base64 string. Then you can simple pull the string from the database and display it in a div. We used the NgCordova camera and then just pass in the data from the takePhoto function.
$scope.takePhoto = function () {
$ionicScrollDelegate.scrollTop();
console.log('fired camera');
$scope.uploadList = false;
$ionicPlatform.ready(function() {
var options = {
quality: 100,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: false,
encodingType: Camera.EncodingType.PNG,
targetWidth: 800,
targetHeight: 1100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
$cordovaCamera.getPicture(options).then(function (imageData) {
$ionicLoading.show({
template: 'Processing Image',
duration: 2000
});
$scope.image = "data:image/png;base64," + imageData;
if (ionic.Platform.isAndroid() === true) {
$scope.Data.Image = LZString.compressToUTF16($scope.image);
$scope.Data.isCompressed = 1;
} else {
$scope.Data.Image = $scope.image;
$scope.Data.isCompressed = 0;
}
if ($scope.tutorial) {
$scope.showAlert("Instructions: Step 3", '<div class="center">Now that you have taken a photo of the POD form, you must upload it to the server. Press the upload doc button in the bottom right of the screen.</div>');
}
$scope.on('')
}, function (err) {
console.log(err);
});
}, false);
};
$scope.UploadDoc = function () {
var req = {
method: 'POST',
url: ffService.baseUrlAuth + 'cc/upload',
headers: {
'x-access-token': ffService.token
},
data: $scope.Data
};
if ($scope.Data.Image === null || $scope.Data.Value === '') {
$scope.showAlert("Uh Oh!", '<div class="center">Please take a photo of your document before attempting an upload.</div>');
} else {
$http(req).success(function (data, status, headers, config) {
localStorage.setItem('tutorial', false);
$scope.tutorial = false;
$scope.getUploads($scope.PODOrder.OrderNo);
$scope.showAlert("Success!", '<div class="center">Your Document has been successfully uploaded!</div>');
$scope.uploadList = true;
}).error(function (data, status, headers, config) {
$rootScope.$broadcast('loading:hide');
$scope.showAlert("Something went wrong!", '<div class="center">Please make sure you have an internet connection and try again.</div>');
}).then(function(data, status, headers, config){
$scope.Data.Image = null;
});
}
};

Related

convert from video uri to blob is not working on iOS using ionic framework

I am using the following code to convert the video file to blob for iOS.
Takevideo()
{
const options: CameraOptions = {
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
destinationType: this.camera.DestinationType.DATA_URL,
mediaType: this.camera.MediaType.VIDEO
}
this.camera.getPicture(options).then(async (videoUrl) => {
debugger;
this.selectvideopath=null;
var filename = videoUrl.substr(videoUrl.lastIndexOf('/') + 1);
var dirpath = videoUrl.substr(0, videoUrl.lastIndexOf('/') + 1);
dirpath = dirpath.includes("file://") ? dirpath : "file://" + dirpath;
try {
var dirUrl = await this.file.resolveDirectoryUrl(dirpath);
var retrievedFile = await this.file.getFile(dirUrl, filename, {});
this.makeFileIntoBlob(retrievedFile.nativeURL);
} catch(err) {
return this.ionLoader.showAlert("Something went wrong.");
}
}, (err) => {
// Handle error
});
}
makeFileIntoBlob(_imagePath) {
return new Promise((resolve, reject) => {
console.log("makefileintoblob", +_imagePath);
let fileName = "";
this.file
.resolveLocalFilesystemUrl(_imagePath)
.then(fileEntry => {
let { name, nativeURL } = fileEntry;
let path = nativeURL.substring(0, nativeURL.lastIndexOf("/"));
console.log("path", path);
console.log("fileName", name);
fileName = name;
var buffer=this.file.readAsArrayBuffer(path, name);
console.log("makefileintoblob buffer: " +buffer);
this.Videodatas.push({vdodata:buffer});
return this.file.readAsArrayBuffer(path, name);
})
.then(buffer => {
this.ionLoader.showAlert('2:'+buffer);
console.log("makefileintoblob buffernew: " +buffer);
let imgBlob = new Blob([buffer], {
type: "video/MOV"
});
console.log(imgBlob.type, imgBlob.size);
resolve({
fileName,
imgBlob
});
})
.catch(e => reject(e));
});
}
But the following block is not executed.
.then(buffer => {
this.ionLoader.showAlert('2:'+buffer);
console.log("makefileintoblob buffernew: " +buffer);
let imgBlob = new Blob([buffer], {
type: "video/MOV"
});
console.log(imgBlob.type, imgBlob.size);
resolve({
fileName,
imgBlob
});
I have already installed the packages:
npm install --save #ionic-native/file-transfer
npm install cordova-plugin-file-transfer
npm install cordova-plugin-file
Can anyone please help me to resolve this issue.

html2pdf creates a blank PDF and somethings shows a security error 'The operation is insecure' on iOS 16.x.x

The html2pdf.js creates a Blank PDF or throws an error 'The operation is insecure' on new iOS 16.0.2.
Below is the html2pdf config:
function generatePDF(true) {
return new Promise(function(resolve, reject) {
var element = document.getElementById("main");
var options = {
filename: 'document.pdf',
image: {
type: 'jpeg',
quality: 0.5
},
html2canvas: {
scrollX: 0,
scrollY: 0,
scale: window.devicePixelRatio && window.devicePixelRatio > 1 ? 0.8 : 1
},
jsPDF: {
unit: 'pt',
format: 'a4',
orientation: 'portrait'
}
};
var pdf = html2pdf().set(options).from(element);
pdf.outputPdf('datauristring').then(function(data) {
// if (true)
// pdf.save();
resolve({
data: data.replace("data:application/pdf;filename=generated.pdf;base64,", ""),
type: "data:application/pdf"
});
}).catch(function(e) {
alert('catch: ' + e);
reject();
});
});
}
html2pdf.js version: 0.10.1
https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js
I have noticed, 'scale' property of 'html2canvas' creates the security error.
However, the above code works in earlier version of iOS.
I wonder what am I missing out from the config?
Thanks

ionic 2 how to HTTP.post image send the server side in ionic 2 / 3

I'm building an app with Ionic 2. I need to take a photo from gallery or camera and upload this picture to my server. I have this code that opens the Gallery and takes a picture. without base64Image, how can upload image.
private accessGallery(): void {
let options = {
quality: 75,
// sourceType: this.camera.PictureSourceType.SAVEDPHOTOALBUM,
// destinationType: this.camera.DestinationType.DATA_URL,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
// encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
}
this.imagePicker.getPictures(options).then((results) => {
this.imageURI = new Array();
for (var i = 0; i < results.length; i++) {
console.log('Image URI: ' + results[i]);
this.imageURI.push(normalizeURL(results[i]));
}
console.log("Body images Name*******:-=" + this.imageURI);
this.uploadFile();
}, (err) => { });
}
uploadFile() {
let body:any = new FormData();
body = {
images: this.imageURI
}
let headers = new Headers({
'token': this.token,
'sid': this.sid,
'user': this.user,
'to': this.to,
'node': this.node,
'type': 'image'
});
let options = new RequestOptions({ headers: headers });
console.log("header ----" + JSON.stringify(headers));
console.log("images data body----" + JSON.stringify(body));
this.http.post(this.apiURL, body, options)
.map(res => res.json())
.subscribe(
data => {
console.log(data);
},
err => {
console.log("ERROR!: ", err);
}
);
}
Error :- ERROR!: Response with status: 0 for URL: null

Phonegap Cordova FileSystem not persistent on iOS?

I am working on an app for iOS and Android, and I am using Cordovas File plugin to save some data to a file on the device.
This file will contain information about the user, so he/she does not have to log in every time they use the app, so the information has to be there even if the app is exited and relaunched.
On Android this works fine:
window.requestFileSystem(LocalFileSystem.PERSISTENT, 20*1024*1024, app.onFileSystemSuccess, fail);
On Android the data I save is there next time I open the app, but on iOS the file is empty (or not existing).
Does this not work for iOS?
Here is the whole source:
var app = {
initialize: function()
{
this.bindEvents();
},
bindEvents: function()
{
document.addEventListener('deviceready', this.onDeviceReady, false);
},
onDeviceReady: function()
{
app.initAPP();
},
initAPP: function()
{
window.requestFileSystem(LocalFileSystem.PERSISTENT, 20*1024*1024, app.onFileSystemSuccess, fail);
},
onFileSystemSuccess: function(FS)
{
FS.root.getDirectory('MyAPPDir', {create:true}, app.gotDir, fail);
},
gotDir: function(Dir)
{
app.appRoot = Dir;
try{
app.appRoot.getFile('authInfo.txt', {create:true}, function(fileEntry){
fileEntry.file(function(file){
alert('Got file authInfo.txt')
var Reader = new FileReader();
Reader.onloadend = function(e){
alert(e.target.result);
if( e.target.result == '' ){
$('#container').load('login.html');
}
else{
document.authInfo = e.target.result;
alert(e.target.result);
alert('You are now auhtorized');
}
}
Reader.readAsText(file);
})
})
} catch(e){
$('#container').load('login.html');
}
},
authUser: function()
{
email = $("#email").val();
password = $("#password").val();
$.ajax({
url: AUTH_URL,
type: 'POST',
data:{
email: email,
password: password
},
success: function(data){
resp = $.parseJSON(data);
if( resp.status == 'success' ){
try{
app.appRoot.getFile('authInfo.txt', {create:true}, function(fileEntry){
fileEntry.createWriter(function(writer){
writer.truncate(0);
writer.onwriteend = function(){
writer.write(resp);
writer.onwriteend = function(){
alert('Wrote '+JSON.stringify(resp)+' to '+fileEntry.toURL());
}
}
});
});
}
catch (e){
alert(e);
}
} else {
alert(resp.message);
}
}
});
}
};
function fail(a){
alert(a);
}
I get this message in iOS:
Wrote {.......myjson.....} to cdvfile://localhost/persistent/MyAPPDir/authInfo.txt
But then when it tries to read it on launch it seems like the file does'nt exist any more, or is empty?

Highcharts columns height in phantomjs generated pdf

I am trying to generate a pdf with phantomjs from a page that's using highcharts. This is the script I am using
var port, server, service
system = require('system');
var page = require('webpage').create();
page.onError = function (msg, trace) {
console.log(msg);
trace.forEach(function(item) {
console.log(' ', item.file, ':', item.line);
})
}
var fs = require('fs');
function loadFile(name){
if(fs.exists(name)){
console.log(name+ " File exist");
return fs.open(name,"r");
}else {
console.log("File do not exist");
}
}
if (system.args.length !== 2) {
console.log('Usage: serverkeepalive.js <portnumber>');
phantom.exit(1);
} else {
port = system.args[1];
console.log('port: ' + port);
server = require('webserver').create();
service = server.listen(port, { keepAlive: true }, function (request, response) {
console.log('Request at ' + new Date());
console.log(JSON.stringify(request, null, 4));
console.log('ProjectId:' + request.headers.projectId)
var projectReportPage = 'http://localhost:55073/' + request.headers.projectId;
console.log(projectReportPage);
console.log(JSON.stringify(request.cookies, null, 4));
phantom.cookiesEnabled = true;
phantom.addCookie({
'name': 'hello', /* required property */
'value': 'helloFromPhantomJS', /* required property */
'domain': 'localhost', /* required property */
'expires': (new Date()).getTime() + 3600 /* <- expires in 1 hour */
});
console.log(JSON.stringify(phantom.cookies, null, 4));
page.paperSize = {
format: 'A4',
orientation: 'portrait',
margin:'1cm' };
page.open(projectReportPage, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
} else {
console.log('Page obtained');
var reportName = 'report_' + request.headers.projectId + '.pdf';
page.evaluate( function(){$('h1').css('color', 'red');});
page.render(reportName);
var body = fs.absolute(reportName);
//var body = page.renderBase64('pdf');
// var fi = loadFile(reportName);
// var body = fi.read();
// var rawBody = fs.read(reportName);
// console.log(rawBody);
// var body = base64Encode(rawBody);
console.log(body);
response.statusCode = 200;
response.headers = {
'Cache': 'no-cache',
'Content-Type': 'application/pdf',
'Connection': 'Keep-Alive',
'Content-Length': body.length
};
response.write(body);
response.close();
}
});
console.log('After page open handler');
});
if (service) {
console.log('Web server running on port ' + port);
} else {
console.log('Error: Could not create web server listening on port ' + port);
phantom.exit();
}
}
When viewing the page, the chart looks like this:
http://i.imgur.com/kVImodv.png
This is what it looks like on the pdf:
http://i.imgur.com/vGon6vb.png
Any insights on why this happens would be appreciated!
The problem is that PhantomJS immediately takes a snapshot when the page is loaded. However, the Highcharts graph has an animation which builds up the graph.
This means the graph is not completely built up when PhantomJS is taking the snapshot. There are two possible solutions.
1. Skip the Highcharts animations
Add this to your graph configuration object.
plotOptions: {
series: {
animation: false
}
}
Source
2. Add a delay when taking a snapshot
page.open(address, function (status) {
window.setTimeout(function () {
page.render(output);
phantom.exit();
}, 200);
}
Source

Resources