Processing multiple simultaneous uploads with Cordova - angularjs

I want to upload 4 images from an ionic app to server side made using sails js.
An user can upload many images so before submit a form so I save all images in an array as its shown below
var cameraOptions = {
quality: 100,
destinationType: Camera.DestinationType.NATIVE_URI,
sourceType : Camera.PictureSourceType.CAMERA,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 500,
targetHeight: 500,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false,
allowEdit:true
};
var success = function(data){
$mdDialog.hide();
if(key==null)
{
compteurImage =compteurImage+1;
$scope.$apply(function () {
$scope.imgURI.push(data);
});
$scope.nombreImage=compteurImage;
}
else
{
$scope.$apply(function () {
$scope.imgURI[key]=data;
});
}
$rootScope.image=$scope.imgURI;
};
After having had all the images in an array, I loop on the array and I send each image to the server as shown below
for (var i = 0; i<$rootScope.image.length; i++) {
if (keepGoing) {
var options = new FileUploadOptions();
var params = {};
params.idArticle =response.article.idArticle;
var url=$rootScope.image[i].substr($rootScope.image[i].lastIndexOf('/') + 1);
options = {
fileKey: "file",
fileName:i+(url.split('?')[0]),
mimeType: "image/png",
idArticle: response.article.idArticle
};
options.params=params;
var failed = function (err) {
console.log(err);
keepGoing = false;
};
var success = function (result) {
count++;
if(count==$rootScope.image.length)
{
console.log("success");
}
};
var ft = new FileTransfer();
ft.upload($rootScope.image[i], Globals.urlServer + Globals.port + "/article/uploadImage", success, failed, options);
}
Server side the controller in charge of upload image is /article/uploadImage
uploadImage:function(req,res)
{
req.file('file')
.upload({ dirname: '../../assets/imagesArticle'},function (err, uploadedFiles) {
if (err) return res.serverError(err);
else {
var chemin = '';
var type = '';
uploadedFiles.forEach(function (file) {
chemin = require('path').basename(file.fd);
type = file.type;
Image.create({cheminImage:chemin, typeImage:type,article:req.body.idArticle}).exec(function(err,image){
if (err)
{
res.send({success:false});
}
if(image)
{
res.send({success:true});
}
})
});
}
});
},
My issue is if regardless how many pictures I upload, when I look image directory on server side, images are always identical and correspond to the last image of the images array. For example if I upload 3 differents images, on server side I get 3 identicals images whose correspond to the third or last image in array.
how can I fix it ?

Related

Ionic Photo Upload - File to Base64 String

I am working on an Ionic App that is communicating with a rails API. I have users, and user have pictures. I have been able to follow this guide about how to allow users to grab images natively from their phone images.
this allows the user to grab an image from their phone
$ionicPlatform.ready(function() {
$scope.getImageSaveContact = function() {
// Image picker will load images according to these settings
var options = {
maximumImagesCount: 1,
width: 800,
height: 800,
quality: 80
};
$cordovaImagePicker.getPictures(options).then(function (results) {
// Loop through acquired images
for (var i = 0; i < results.length; i++) {
$scope.collection.selectedImage = results[i]; // We loading only one image so we can use it like this
window.plugins.Base64.encodeFile($scope.collection.selectedImage, function(base64){ // Encode URI to Base64 needed for contacts plugin
$scope.collection.selectedImage = base64;
});
}
console.log("results");
console.log(results);
}, function(error) {
console.log('Error: ' + JSON.stringify(error));
});
};
});
The problem is, it is not running (or appears not to not be running) the window.plugins.Base64.encodeFile line that encodes a file. Right now, it is only the image file and not the Base64 encoded string.
How do I get this function to run, after I have grabbed a file from my device camera?
i was able to figure it out, answer is below
from an old project https://github.com/aaronksaunders/firebaseStorageApp/blob/master/www/js/app.js#L132
return $cordovaFile.readAsArrayBuffer(path, fileName)
.then(function (success) {
// success - get blob data
var imageBlob = new Blob([success], { type: "image/jpeg" });
})
add this camera plugin
cordova plugin add cordova-plugin-camera
this returns image in base 64 by default..
$scope.choosePhoto = function () {
$scope.myPopup.close();
var options = {
quality: 75,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 300,
targetHeight: 300,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
$cordovaCamera.getPicture(options).then(function (imageData) {
$scope.imgURI = "data:image/jpeg;base64," + imageData;
}, function (err) {
// An error occured. Show a message to the user
});
}
more details can be found here
http://ngcordova.com/docs/plugins/camera/
hope this helps...
I was able to figure this out by piecing together a bunch of stuff, especially w/ the rails side. The idea is to click a button to get an image, pick one from your camera roll, convert that image to a base64 string, then send that image to the server.
my current stack is rails 4, ionic/angular v1. hopefully this helps someone else.
angular controller
function toDataUrl(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var reader = new FileReader();
reader.onloadend = function() {
callback(reader.result);
}
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}
$scope.grabImage = function () {
var options = {
maximumImagesCount: 1,
width: 800,
height: 800,
quality: 80
};
$cordovaImagePicker.getPictures(options).then(function (results) {
$scope.dataImg = results;
return toDataUrl($scope.dataImg, function(base64Img) {
$scope.base64 = base64Img;
$state.go($state.current, {}, {reload: false});
})
}, function(error) {
$scope.message = "Error: Failed to Attach Image";
var alertPopup = $ionicPopup.alert({
title: 'User Photos',
templateUrl: 'templates/modals/success_or_error.html',
scope: $scope
});
});
}
rails controller
def create
image = Paperclip.io_adapters.for(params[:image_file])
image.class.class_eval { attr_accessor :original_filename, :content_type }
image.original_filename = "mu_#{#current_mobile_user.id}_#{#current_mobile_user.pictures.count}.jpg"
image.content_type = "image/jpeg"
#picture = #current_mobile_user.pictures.create(image: image, imageable_id: #current_mobile_user.id)
if #picture.save
render json: ['Picture Uploaded!'], status: :created
else
render json: [#picture.errors.full_messages.to_sentence], status: :unprocessable_entity
end
end

Ionic 1, firebase storage, cordova.getPictures, not save images?

I'm programming an application
with ionic 1 and firebase 3.
I want to upload an image to the storage of firebase.
When I use html fileupload the image is saved but when i use "cordova.getPictures" the image is not saved.
The code:
.controller("PhotosCtrl",function($scope,$firebaseArray,$firebaseAuth,$firebaseObject, $timeout, $cordovaImagePicker, $ionicPopup){
$scope.upFile = function(){
pickTheImage().then(function(_image) {
processImage(_image);
})
}
function pickTheImage() {
var options = {
maximumImagesCount: 1,
width: 320,
quality: 80
};
return $cordovaImagePicker.getPictures(options).then(function (results) {
return results[0];
})
}
function processImage(_image) {
fetch(_image).then(function (_data) {
return _data.blob()
}).then(function (_blob) {
var task=firebase.storage().ref('images/12312355.jpg').put(_blob);
task.on('state_changed',
function progress(snapshot){
},
function error(err){
$ionicPopup.alert({
title: err
})
},
function complete(){
$ionicPopup.alert({
title: "Imagen guardada!"
})
}
);
})
}
})
Capturing image from camera will return the imageUrl. If you want to convert to blob type then using the below code in processImage function.
//Read the file entry from the file URL
resolveLocalFileSystemURL(imgUrl, function (fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function () {
var imgBlob = new Blob([this.result], {
type: file.type
});
var imgFile = imgBlob;
};
reader.readAsArrayBuffer(file);
});
}, function () {
//on Error
});
You can also refer
http://ourcodeworld.com/articles/read/22/solve-native-path-of-android-content-if-resolvelocalfilesystemurl-doesn-t-work

How to convert this image to json in angularjs?

i take my picture with a camera after i want to post in the web service
so how to convert this image to format Json
my controller changed:
facebookExample.controller('MainCtrl', function($scope,$cordovaOauth, $localStorage, $location,$ionicPopup,$state,$http, Camera) {
$scope.fileArray = [];
$scope.imgContent = {};
$scope.imageStrings = [];
$scope.getPhoto = function(files) {
Camera.getPicture().then(function(imageURI) {
console.log(imageURI);
$scope.lastPhoto = imageURI;
angular.forEach(files, function(flowFile, i) {
var uri = imageURI;
$scope.imageStrings[i] = uri;
$scope.imgContent = {
fileName: flowFile.name,
fileContent: uri
};
fileReader.readAsDataURL(flowFile.file);
$scope.fileArray.push($scope.imgContent);
});
}, function(err) {
console.err(err);
}, {
quality: 75,
targetWidth: 320,
targetHeight: 320,
saveToPhotoAlbum: false
});
console.log("JSON.stringify($scope.fileArray)");
console.log(JSON.stringify($scope.fileArray));
};
You can try this code.
$scope.fileArray = [];
$scope.imgContent = {};
$scope.imageStrings = [];
$scope.processFiles = function(files) {
angular.forEach(files, function(flowFile, i) {
var fileReader = new FileReader();
fileReader.onload = function(event) {
var uri = event.target.result;
$scope.imageStrings[i] = uri;
$scope.imgContent = {
fileName: flowFile.name,
fileContent: uri
};
};
fileReader.readAsDataURL(flowFile.file);
$scope.fileArray.push($scope.imgContent);
});
console.log(JSON.stringify($scope.fileArray));
};
Or here is the jsfiddle
I tried this way and worked in one of my projects.Check it out.
Maybe it works for you too!
$cordovaCamera.getPicture(options).then(function(imagePath)
{
var promise = $service(imagePath);
promise.success(function(data)
{
//after service
});
}, function(error)
{
//An error occured
});
}
And here is an example service
$service=function(photo)
{
$http.defaults.headers.common["Accept"] = "application/json";
$http.defaults.headers.post["Content-Type"] = "application/json";
var data=JSON.stringify({photo:photo});
return $http.post("your webservice url",data);
};
Edit 1:Forgot to give you the camera options.Here you are!
var options = {
quality: 100,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
encodingType: Camera.EncodingType.JPEG,
cameraDirection: Camera.Direction.FRONT,
correctOrientation: true,
saveToPhotoAlbum: true
};

Open the image gallery with Ionic/angularjs

How do I access with Ionic/angularjs on the image gallery? I just want to open the image gallery per button click. How is that possible?
You can use the cordova camera plugin
cordova plugin add org.apache.cordova.camera
Plugin Reference:
https://github.com/apache/cordova-plugin-camera
Sample code
$scope.getPhoto = function() {
var options = {
quality: 50,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.SAVEDPHOTOALBUM,
mediaType: Camera.MediaType.ALLMEDIA,
saveToPhotoAlbum: true
};
$cordovaCamera.getPicture(options).then(function(imageData) {
console.log("img URI= " + imageData);
//Here you will be getting image data
}, function(err) {
alert("Failed because: " + err);
console.log('Failed because: ' + err);
});
};
You need to just set sourceType option to Camera.PictureSourceType.SAVEDPHOTOALBUM
You can get cordova plugin for ImagePicker by using the following link:
http://ngcordova.com/docs/plugins/imagePicker/
Example:
$scope.OpenGallery = function() {
var options = {
maximumImagesCount: 1,
width: 350,
height: 500,
quality: 50
};
$cordovaImagePicker.getPictures(options).then(function (results) {
console.log(results);
},function(error) {
console.log(error);
});
}
Guys at Ionic made this example: https://github.com/driftyco/ionic-example-cordova-camera/blob/master/plugins/org.apache.cordova.camera/doc/index.md
As a second option, you can try with the imagePicker plugin.
Example:
module.controller('ThisCtrl', function($scope, $cordovaImagePicker) {
var options = {
maximumImagesCount: 10,
width: 800,
height: 800,
quality: 80
};
$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
});
});

Take in-app photo with Cordova Camera and upload it to Parse.com

I'm building an Ionic/Cordova app which uses Parse.com as a BaaS. It uses the ngCordova Camera plugin to control the device camera. The use-case is click a button, take a picture and have it upload to Parse. I've been researching the problem for a week now and still can't figure out why I can't get it to work.
The controller:
.controller('cameraCtrl', function($scope, camera) {
var cameraOptions = {
quality: 75,
destinationType: 0,
encodingType: 0,
targetWidth: 300,
targetHeight: 300,
mediaType: 0,
correctOrientation: true,
saveToPhotoAlbum: true
};
};
$scope.takePicture = function() {
cameraOptions.sourceType = 1;
navigator.camera.getPicture(onSuccess, onFail, cameraOptions);
}
$scope.selectPicture = function() {
cameraOptions.sourceType = 0;
navigator.camera.getPicture(onSuccess, onFail, cameraOptions);
}
function onSuccess(picture) {
File.upload(picture)
.success(function(data) {
// upload finish
});
$scope.$apply(function() {
$scope.preview = 'data:image/jpeg;base64,' + picture;
});
}
function onFail(resp) {
alert('Error: ' + resp);
}
});
The service:
angular.factory('File', function ($http) {
return {
upload: function (photo) {
var json = {
'base64': photo,
'_ContentType': 'image/jpeg'
}
var config = {
method: 'POST',
url: 'https://api.parse.com/1/files/pict.jpg',
data: json,
headers: {
'X-Parse-Application-Id': 'PCm0kDVeThvRcdFuS9lITrmskEhqjbqwFAydL2Lr',
'X-Parse-REST-API-Key': 'FhasGkTl0BLpJuLLJvPB2NFwlccXzVbirktdngXN'
}
};
return $http(config);
}
}
});
The HTML:
<button class="button" ng-click="takePicture()">
Any ideas as to why this doesn't work? Is there a better or more simple way to accomplish this? Any examples of this working somewhere? I've tried a dozen different solutions over the week and haven't found anything that works for my use-case. Thanks!
It would be helpful is you provided any error messages, but here is how I have solved the issue
var imageFile = new Parse.File("mypic.jpg", {base64: _params.photo});
console.log(imageFile);
// save the parse file
return imageFile.save().then(function () {
// create object to hold caption and file reference
var imageObject = new ImageObject();
// set object properties
imageObject.set("caption", _params.caption);
imageObject.set("picture", imageFile);
// save object to parse backend
return imageObject.save();
}, function (error) {
console.log("Error");
console.log(error);
});
There is a complete project here showing Parse.com integration with the File Object.
https://github.com/aaronksaunders/dcww/blob/master/www/js/services.js

Resources