getting Blob:URL from $cordovaCamera, Not valid base64 string - angularjs

I am working on cordova mobile application, I need to upload an Image on server. I want to send base64 string to my webapi and there I can convert base64 to Image and save image on server. I am doing this $cordovaCamera in controller as
$scope.takePicture = function () {
var options = {
quality: 75,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false,
correctOrientation: true
};
$cordovaCamera.getPicture(options).then(function (imageData) {
console.clear();
console.log(imageData);
$scope.imgURI = imageData;
$rootScope.ByteData = "data:image/jpeg;base64," + imageData;
}, function (err) {
var alertPopup = $ionicPopup.alert({
title: 'Invalid Image',
template: 'Please upload correct formated image!'
});
});
}
But whenever I run this code I got imageData in form of specific URL like "blob:http%3A//localhost%3A4400/f6c7fc38-a18f-484e-94d1-a52bb4e5fee2", How can I get base64 correct string in this scenario. In my view I am doing like
<ion-view view-title="{{application.CompanyName}}">
<ion-nav-buttons side="primary">
<button class="button" ng-click="saveApplication()">
SAVE
</button>
<button class="button" ng-click="goBack()">
BACK
</button>
</ion-nav-buttons>
<ion-content ng-controller="AppDetailCtrl">
<img ng-show="imgURI !== undefined" width="343px" height="300px" ng-src="{{imgURI}}">
<img ng-show="imgURI === undefined" width="343px" height="300px" ng-src="http://placehold.it/300x300">
<button class="button" ng-click="takePicture()">Upload Picture</button>
</ion-content>
</ion-view>

Actually I want to convert that blob image url type to base64 string and I was missing bellow method of converting like
function convertImgToBase64(url, callback, outputFormat) {
var canvas = document.createElement('CANVAS'),
ctx = canvas.getContext('2d'),
img = new Image;
img.crossOrigin = 'Anonymous';
img.onload = function () {
var dataURL;
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0);
dataURL = canvas.toDataURL(outputFormat);
callback.call(this, dataURL);
canvas = null;
};
img.src = url;
}
convertImgToBase64(imageData, function (base64Img) {
$rootScope.ByteData = base64Img;
});

Related

Uploading files in Ionic application using Web API

My issue is as below.
I have given WEB API where I have to add boards picture.
What I have to DO?
User should able to select Image from Phone
User can add Name of board
When user click on submit, entered board name and board image should post using Web API with method of PUT. Here below is WEB API Details
WEB API Details
Header
URL: https://example.com
Content-Type: | Content Type |
Method: PUT
Data
board_id: 321
board_title: | Title |
board_background: | File |
I have used cordovaImagePicker plugin to select image and then I get stuck to uploading it to Server.
I can use cordova file transfer plugin but I think that will not help me in this case as there is no specified place to store image. All the file management done by WEB API, we have to just post file with Data.
After trying a lot solution I have come with below answer.
Board.html
<ion-view>
<ion-nav-bar class="bar">
<ion-nav-title>
<h1 class="title">
Create Board
</h1>
</ion-nav-title>
</ion-nav-bar>
<form name="boardForm" ng-submit="addBoard(data)">
<ion-content padding="false" scroll="true" has-bouncing="false">
<div id="form">
<div style="text-align: center; padding-top: 2%; padding-bottom: 2%;">
<div id="image-preview">
<label for="image-upload" id="image-label"><img src="{{ImagePrefix}}/task_plus.png" alt=""/></label>
<input type="file" name="board_background" id="image-upload" file-model="data.board_background">
</div>
<p>Add Cover</p>
</div>
<ion-list>
<ion-item style="background-color: #F8F8F8;">
<label class="control-label" for="board_name">BOARD NAME</label>
</ion-item>
<ion-item ng-class="{true:'error'}[submitted && boardForm.board_title.$invalid]">
<input type="text" id="board_name" ng-model="data.board_title"
placeholder="Add a Name" name="board_title" required>
<p ng-show="submitted && boardForm.board_title.$error.required">
Please enter a board name
</p>
</ion-item>
</ion-list>
</div>
</ion-content>
<ion-footer-bar>
<button class="button button-block control-button bottomOfPage"
ng-click="submitted = true">
CREATE
</button>
</ion-footer-bar>
</form>
</ion-view>
directive
.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function () {
scope.$apply(function () {
modelSetter(scope, element[0].files[0]);
});
});
}
};
}])
Controller
.controller('ManageBoardCtrl', function ($scope, $http, $ionicPopup, $state, BoardService) {
$scope.submitted = false;
$scope.data = {};
$scope.addBoard = function(formData) {
BoardService.CreateBoard(formData).then(function(response) {
if (response === "success") {
$ionicPopup.alert({
title: "Success",
template: "Board created successfully"
});
}
}, function (response) {
$ionicPopup.alert({
title: "Failed",
template: "Somethings wrong, Can not create boards at now."
});
});
}
})
Service
.service('BoardService', function ($q, $http) {
var getUrl = API_URL + "boards";
var createBoard = function (fData) {
var formData = new FormData();
formData.append("board_title", fData.board_title);
formData.append("board_background", fData.board_background);
return $q(function (resolve, reject) {
$http({
transformRequest: angular.identity,
method: 'POST',
url: getUrl,
headers: { 'Content-Type': undefined },
data: formData
}).success(function (response) {
if (response.success === true) {
resolve('success');
} else {
reject('fail');
}
}).error(function () {
reject('requesterror');
});
});
};
return {
CreateBoard: createBoard
};
})
After deploying application for android / iPhone file selection will handle the browsing Images based on the OS.
One simple thing I can suggest,
Use input["file"] tag to select the image. You will get the file object and a temporary url. with this url you can show the image in the form.
Then use formData to append the image and the other field.
e.g.
var fd = new FormData();
fd.append('board_background', $scope.image, $scope.image.name);
fd.append('board_id', 321);
fd.append('board_title', 'Dummy title');
var xhr = new XMLHttpRequest();
xhr.open('PUT', YOUR_URL, true);
xhr.onload(function(res){
// Write your callback here.
});
// Send the Data.
xhr.send(fd);
Hope it will help you and meet your requirements.
First of all to need to select the image from device.
vm.getImages = function () {
var options = {
quality: 70,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
allowEdit: true,
correctOrientation:true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 300,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: true
};
navigator.camera.getPicture(onSuccess, onFail, options);
function onSuccess(imageURI) {
vm.image = "data:image/jpeg;base64," + imageURI;
vm.imageURI = imageURI;
}
function onFail(message) {
console.log('Failed because: ' + message);
}
};
You can change the source type for input if needed.
sourceType: Camera.PictureSourceType.CAMERA,
On success you get ImageURI either use it directly or convert it to base64 as mentioned below for uploading.
vm.image = "data:image/jpeg;base64," + imageURI;
After this you can use the FileTransfer plugin to upload file and track the progress at the same time.
cordovaFileTransfer.upload()
.then(function (result) {},
function (err) {},
function (progress) {});
Below link will definitely help you:
http://ionicmobile.blogspot.in/2015/10/jquery-file-upload.html
Make the appropriate changes if needed. Any help let me know...

ngcordova camera images in a list from array

I need to push my base64 string into an empty array so that I can make use of it in $http post.i don' understand when i have made mistake. when i use chome://inspect/#device i get ERROR:-No Content-Security-Policy meta tag found. Please add one when using the cordova-plugin-whitelist plugin and after photo was taken i get net::ERR_FILE_NOT_FOUND but i can list my photos
HTML
<ion-header-bar class="bar-stable">
<h1 class="title">OB3 SNAPSHOT</h1>
<button class="button button-clear button-large ion-ios-camera" style="align:right" ng-click="takePicture()"></button>
</ion-header-bar>
<ion-content>
<img ng-show="imgURI !== undefined" ng-src="{{imgURI}}">
<img ng-show="imgURI === undefined" ng-src="http://placehold.it/300x300">
<!--<button class = "button" ng-click="takePicture()">Take Picture</button>-->
<ul class="list">
<li class="item" ng-repeat="i in myImage">
<img ng-src="{{baseURL+i}}" ng-click="clickImage()">
</li>
</ul>
</ion-content>
AngularJS
exampleApp.controller("ExampleController", function($scope, $cordovaCamera) {
$scope.myImage = [];
$scope.baseURL = 'data:image/jpeg;base64,';
$scope.clickImage = function() {
var postObject = {
data: {
"width": 32,
"height": 32,
"mimetype": "image/png",
"name": "Image",
"bindaryData": $scope.myImage[0]
}
}
$http.post(" url",
postObject)
.success(function(response) {
$scope.names = response.response.data;
console.log(response);
console.log(response.response.data);
})
.error(function(response) {
console.log(response);
alert('post is error');
});
};
$scope.takePicture = function() {
navigator.camera.getPicture(onSuccess, onFail, {
quality: 75,
targetWidth: 320,
targetHeight: 320,
destinationType: 0
});
function onSuccess(imageData) {
$scope.imgURI = imageData;
$scope.myImage.push($scope.imgURI);
$scope.$apply();
}
function onFail(message) {
alert('Failed because: ' + message);
}
};
});
Actually the pushing of $scope.imgURI is working perfectly.But your view is not updated.please take two photos.Then you can understand your problem.By adding $scope.$apply() will resolve your issue
Just try this code,
Controller
$scope.myImage = [];
$scope.baseURL = 'data:image/jpeg;base64,';
$scope.takePhoto = function() {
navigator.camera.getPicture(onSuccess, onFail, {
quality: 75,
targetWidth: 320,
targetHeight: 320,
destinationType: 0
});
function onSuccess(imageData) {
$scope.imgURI = imageData;
$scope.myImage.push($scope.imgURI);
$scope.$apply();
}
function onFail(message) {
alert('Failed because: ' + message);
}
};
HTML
<button ng-click="takePhoto()">Capture</button>
<li ng-repeat="i in myImage">
<img ng-src="{{baseURL+i}}">
</li>
Refer

how to convert image into base64 string?

hello I am trying to make simple application in ionic using camera or select file from gallery or file system and send to / or upload to a server.
I found one plugin which capture one image and send base64 string
here is plugin
http://ngcordova.com/docs/plugins/camera/
using this I am able to get base64 string
$cordovaCamera.getPicture(options).then(function(imageData) {
var image = document.getElementById('myImage');
image.src = "data:image/jpeg;base64," + imageData;
}, function(err) {
// error
});
that base64 string I used to send to server
But my problem is that when I use this plugin image gallary plugin
http://ngcordova.com/docs/plugins/imagePicker/
it send me only image url (where is in memory) .can we get base64 string after selecting the image from image picker.
$cordovaImagePicker.getPictures(options)
.then(function (results) {
for (var i = 0; i < results.length; i++) {
console.log('Image URI: ' + results[i]);
}
}, function(error) {
// error getting photos
});
In other words when I using camera I am getting base64 string as shown above.But when I use image picker plugin I am getting image url.can I get base64 string .so that I am able to send or upload on server .
how to convert image url to base64 string ?
Try this 100% working code. First you have to Download ngCordova.min.js file and include it in your index.html file. Follow this code.
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope,$cordovaCamera) {
$scope.imgUrl;
$scope.dataImg;
$scope.tackPicture = function(){
var options = {
quality: 50,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false,
correctOrientation:true
};
$cordovaCamera.getPicture(options).then(function(imageData) {
//var image = document.getElementById('myImage');
$scope.dataImg = imageData; // <--- this is your Base64 string
$scope.imgUrl = "data:image/jpeg;base64," + imageData;
}, function(err) {
// error
});
}
})
.controller('ChatsCtrl', function($scope, Chats) {
// With the new view caching in Ionic, Controllers are only called
// when they are recreated or on app start, instead of every page change.
// To listen for when this page is active (for example, to refresh data),
// listen for the $ionicView.enter event:
//
//$scope.$on('$ionicView.enter', function(e) {
//});
$scope.chats = Chats.all();
$scope.remove = function(chat) {
Chats.remove(chat);
};
})
.controller('ChatDetailCtrl', function($scope, $stateParams, Chats) {
$scope.chat = Chats.get($stateParams.chatId);
})
.controller('AccountCtrl', function($scope) {
$scope.settings = {
enableFriends: true
};
});
<ion-view view-title="Dashboard">
<ion-content class="padding">
<button class="button icon-left ion-ios-camera button-block button-positive" ng-click="tackPicture()">
OPEN CAMERA
</button>
<div class="item item-avatar">
<img ng-src="{{ imgUrl }}">
<p>{{ dataImg }}</p>
</div>
</ion-content>
</ion-view>
To convert image to base64 you can use HTML5 canvans as mention in
How to convert image into base64 string using javascript
Please refer above question
Use this code
/**
* Convert an image
* to a base64 url
* #param {String} url
* #param {Function} callback
* #param {String} [outputFormat=image/png]
*/
function convertImgToBase64URL(url, callback, outputFormat){
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function(){
var canvas = document.createElement('CANVAS'),
ctx = canvas.getContext('2d'), dataURL;
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
dataURL = canvas.toDataURL(outputFormat);
callback(dataURL);
canvas = null;
};
img.src = url;
}

Strange way to load the google map

I am using AngularJS + ionic and I am trying to create a google map. I am using the plugin cordova to get the exact position of the user and it works. In addition, the map is loaded only when the person takes a photo, there, is where obtendo such data. So there I have no problem, but the way the map is loaded strange, is clipped and navigation is pesima. I leave you my code and a picture of how the map looks.
<map center="{{latitud}}, {{longitud}}" zoom="15" style="width:100%;height:100%;" data-tap-disabled="true" id="mapa_view">
<marker position="{{latitud}}, {{longitud}}" />
</map>
.controller("CamaraCtrl", function($scope,$rootScope, Camera,$cordovaGeolocation) {
var posOptions = {timeout: 10000, enableHighAccuracy: false};
$cordovaGeolocation
.getCurrentPosition(posOptions)
.then(function (position) {
var latitud_actual = position.coords.latitude
var longitud_actual = position.coords.longitude
$scope.latitud = latitud_actual;
$scope.longitud = longitud_actual;
}, function(err) {
// error
});
$scope.mostrar_form = false;
$scope.getPhoto = function() {
Camera.getPicture().then(function(imageURI) {
console.log(imageURI);
$scope.lastPhoto = imageURI;
$scope.mostrar_form = true;
}, function(err) {
console.err(err);
}, {
quality: 75,
targetWidth: 320,
targetHeight: 320,
saveToPhotoAlbum: false
});
};
$scope.getPhoto();
})

Ionic-Angular.js Taking pictures & sending to server: null images

So I have managed to use a custom directive to upload images to my server, through Angular.js.
I have also managed to implement the camera functionality from Cordova.
Now I am trying to connect the two, but when sending images to the server, they get stored as null. I believe the problem lies in the fact that I was using an input field to get the image, and it was getting the full Object, and now I am getting just the image path after I take the picture and send it. My problem is, I don't really understand how I could convert the path to an Object, IF that is the problem?
index.html
<form class="form-horizontal" role="form">
<button class="picButton" ng-click="getPhoto()" class="button button-block button-primary">Take Photo</button>
<img ng-src="{{lastPhoto}}" style="max-width: 100%">
...
</form>
controllers.js
$scope.getPhoto = function() {
Camera.getPicture().then(function(imageURI) {
console.log(imageURI);
$scope.lastPhoto = imageURI;
$scope.upload(); <-- call to upload the pic
},
function(err) {
console.err(err);
}, {
quality: 75,
targetWidth: 320,
targetHeight: 320,
saveToPhotoAlbum: false
});
};
$scope.upload = function() {
var url = '';
var fd = new FormData();
//previously I had this
//angular.forEach($scope.files, function(file){
//fd.append('image',file)
//});
fd.append('image', $scope.lastPhoto);
$http.post(url, fd, {
transformRequest:angular.identity,
headers:{'Content-Type':undefined
}
})
.success(function(data, status, headers){
$scope.imageURL = data.resource_uri; //set it to the response we get
})
.error(function(data, status, headers){
})
}
When printing $scope.lastPhoto I get the image path: file:///var/mobile/Applications/../tmp/filename.jpg
EDIT
Request Headers:
------WebKitFormBoundaryEzXidt71U741Mc45
Content-Disposition: form-data; name="image"
file:///var/mobile/Applications/C65C8030-33BF-4BBB-B2BB-7ECEC86E87A7/tmp/cdv_photo_015.jpg
------WebKitFormBoundaryEzXidt71U741Mc45--
Should this causing the problem? Since I can see I am sending the path but not the image itself..
Before changing, I was using a custom directive, and was using $scope.files to append to my request in the upload function:
<input type="file" file-input="files" multiple onchange="angular.element(this).scope().filesChanged(this);upload();">
<button ng-click="upload()">Upload</button>
I resolve with this code :
$scope.getPhoto = function() {
navigator.camera.getPicture(onSuccess, onFail, { quality: 75, targetWidth: 320,
targetHeight: 320, destinationType: 0 });
//destination type was a base64 encoding
function onSuccess(imageData) {
//preview image on img tag
$('#image-preview').attr('src', "data:image/jpeg;base64,"+imageData);
//setting scope.lastPhoto
$scope.lastPhoto = dataURItoBlob("data:image/jpeg;base64,"+imageData);
}
function onFail(message) {
alert('Failed because: ' + message);
}
}
function dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString = atob(dataURI.split(',')[1]);
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++)
{
ia[i] = byteString.charCodeAt(i);
}
var bb = new Blob([ab], { "type": mimeString });
return bb;
}
after this use append to your formdata like this:
formData.append('photo', $scope.lastPhoto, $scope.publish.name+'.jpg')
This code run on IOS without problem.
I think your problem lies in the 'Content-Type':undefined. For images, you should use 'Content-Type':'image/jpeg'.
I would also add enctype="multipart/form-data" to the <form>.
What I ended up doing was to add destinationType: Camera.DestinationType.DATA_URL in the options of the getPhoto function, and that returns a base64 representation of the image, which I then send over to the server and store in a TextField() (Django):
$scope.getPhoto = function() {
Camera.getPicture().then(function(imageURI) {
console.log(imageURI);
$scope.lastPhoto = imageURI;
$scope.upload(); <-- call to upload the pic
},
function(err) {
console.err(err);
}, {
quality: 75,
targetWidth: 320,
targetHeight: 320,
saveToPhotoAlbum: false,
destinationType: Camera.DestinationType.DATA_URL
});
};
Also, when deadling with Base64 images, remember to call the using:
<img ng-src="data:image/jpeg;base64,{{image}}" />

Resources