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

All we need is an easy explanation of the problem, so here it is.

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>

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

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.

Method 2

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>.

Method 3

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}}" />

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply