I am currently working on an Ionic mobile application which will eventually take photos, attach a location and send them inside a post request to a rails endpoint. After looking at this link and this link and countless others, I have been unable to find any solid information on implementing this particular feature.
I can upload photos through the browser using a html input form, which is then added to the database and is displayed on the app via a get request.
However at the moment when taking a photo on the phone and attempting to send it via a post request directly from the app, only the location information is being received, the image is not being correctly encoded.
Here is the jSON data that has been received, its returning "image_url":"/images/main/missing.png"
.
{ "id":6,"city":"Greater London",
"country":"United Kingdom","created_at":"2015-05-14T21:22:22.825Z",
"updated_at":"2015-05-14T21:22:22.825Z","image_file_name":null,
"image_content_type":null,"image_file_size":null,
"image_updated_at":null,"image_url":"/images/main/missing.png" }
Here is the code:
Angular factory making post request:
.factory('Posts', function($http) {
var o = { posts: [] };
o.getAll = function() {
return $http.get('http://localhost:8100/posts').success(function(data) {
angular.copy(data, o.posts);
});
};
o.addPost = function(post) {
return $http.post('https://shielded-hamlet-4665.herokuapp.com/posts', post);
};
return o;
})
Angular Controller taking photo:
.controller("CameraCtrl", function($scope, $cordovaCamera, $http, Posts) {
var id = 0;
var options = {
quality : 75,
destinationType : Camera.DestinationType.FILE_URI,
sourceType : 1,
allowEdit : true,
encodingType: 0,
targetWidth: 380,
targetHeight: 450,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
function getLocCoords(position) {
$scope.lat = position.coords.latitude;
$scope.lon = position.coords.longitude;
$http.get('http://maps.googleapis.com/maps/api/geocode/json?latlng=' + $scope.lat +',' + $scope.lon + '&sensor=true')
.success(function(data) {
var home = data.results[0].address_components;
for (var i = 0; i < home.length; i++) {
if(home[i].types.indexOf("administrative_area_level_2") > -1) {
$scope.city = home[i].long_name;
break;
};
};
for (var i = 0; i < home.length; i++) {
if(home[i].types.indexOf('country') > -1) {
$scope.country = home[i].long_name;
break;
};
};
})
};
$scope.takePicture = function() {
navigator.geolocation.getCurrentPosition(getLocCoords);
$cordovaCamera.getPicture(options).then(function(imageData) {
$scope.imgURI = imageData;
id ++;
var post = { id: id, country: $scope.country, city: $scope.city, image: $scope.imgURI, likes: 0, comments: [] }
Posts.addPost(post);
}, function(err) {
});
}
Post Controller from the Rails Database:
class PostsController < ApplicationController
skip_before_filter :verify_authenticity_token
def index
@posts = Post.all
render json: @posts, :callback => params['callback'], :content_type => 'application/javascript', :methods => [:image_url]
end
def new
@post = Post.new
end
def create
Post.create(post_params)
redirect_to '/posts'
end
def post_params
params.require(:post).permit(:city, :country, :image)
end
end
I have not done a great deal of work with the ionic framework so please forgive my ignorance. Any help would be greatly appreciated.
Managed to solve this using the cordovaFileTransfer.upload
method.
The rails end point was also filtering params and looking for a post object, with a image string, and only an image string was being provided.
The following code is now working
Angular factory making post request:
.factory('Posts', function($http, $cordovaFileTransfer) {
var o = { posts: [] };
o.getAll = function() {
return $http.get('https://shielded-hamlet-4665.herokuapp.com/posts').success(function(data) {
angular.copy(data, o.posts);
});
};
o.addPost = function(post) {
var options = {
fileKey: "image",
fileName: "image.jpeg",
chunkedMode: false,
mimeType: "image/jpeg",
params: { city: post.city, country: post.country, lat: post.lat, lon: post.lon }
};
$cordovaFileTransfer.upload('http://shielded-hamlet-4665.herokuapp.com/posts', post.image, options)
.then(function(result){
console.log("Code = ok");
}, function(error){
console.log("Code = " + error);
}, function(progress){});
};
return o;
})
Angular Controller taking photo:
.controller("CameraCtrl", function($scope, $cordovaCamera, $http, Posts) {
post = {};
var options = {
quality : 75,
destinationType : Camera.DestinationType.FILE_URI,
sourceType : 1,
allowEdit : true,
encodingType: 0,
targetWidth: 380,
targetHeight: 450,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
function getLocCoords(position) {
post.lat = position.coords.latitude;
post.lon = position.coords.longitude;
$http.get('http://maps.googleapis.com/maps/api/geocode/json?latlng=' + post.lat +',' + post.lon + '&sensor=true')
.success(function(data) {
var home = data.results[0].address_components;
for (var i = 0; i < home.length; i++) {
if(home[i].types.indexOf("administrative_area_level_2") > -1) {
post.city = home[i].long_name;
break;
};
};
for (var i = 0; i < home.length; i++) {
if(home[i].types.indexOf('country') > -1) {
post.country = home[i].long_name;
break;
};
};
})
};
$scope.takePicture = function() {
navigator.geolocation.getCurrentPosition(getLocCoords);
$cordovaCamera.getPicture(options).then(function(imageData) {
post.image = imageData;
Posts.addPost(post);
}, function(err) {});
};
});
Post controller from rails database:
class PostsController < ApplicationController
skip_before_filter :verify_authenticity_token
def index
@posts = Post.all
render json: @posts, :callback => params['callback'], :content_type => 'application/javascript', :methods => [:image_url]
end
def new
@post = Post.new
end
def create
Post.create(post_params)
redirect_to '/posts'
end
def post_params
params.permit(:city, :country, :image, :lat, :lon)
end
end