Get a picture, upload it to the server

I have a localhost with in upload function(post) with the key ‘avatar’.
the upload function works fine when using postman.

now, what i want to do in my ionic app is to get a picture and upload it to the server.

here is my controller:

.controller('newPostCtrl', function($scope, shareData, fileUpload,  $cordovaCamera) {

var imageFile;

//*********Camera**********
$scope.takePicture = function() {
    console.log("sss");
    var options = { 
        quality : 80, 
        destinationType : Camera.DestinationType.DATA_URL, 
        sourceType : Camera.PictureSourceType.CAMERA, 
        allowEdit : true,
        encodingType: Camera.EncodingType.JPEG,
        targetWidth: 266,
        targetHeight: 266,
        popoverOptions: CameraPopoverOptions,
        saveToPhotoAlbum: false
    };

    $cordovaCamera.getPicture(options).then(function(imageData) {
        var image = document.getElementById('myImage');
        image.src = "data:image/jpeg;base64," + imageData;
        imageFile =   imageData;
    }, function(err) {
        console.log("error");
    });
}
//**************************

//save data
$scope.saveData = function(content, title) {

  $scope.uploadFile();
  shareData.getData(title, content, imageFile);
}

$scope.uploadFile = function(){
    var file = imageFile;
    console.log('file is ' + JSON.stringify(file));
    var uploadUrl = "http://192.168.56.1:1337/file/upload";
    fileUpload.uploadFileToUrl(file, uploadUrl);
};
//*********
})

my service:

.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl){
    var fd = new FormData();
    fd.append('file', file);
    $http.post(uploadUrl, fd, {
        transformRequest: angular.identity,
        headers: {'Content-Type': undefined}
    })
    .success(function(){
    })
    .error(function(){
    });
}
}])

the camera works perfectly but when i try to make an upload nothing happens. since im testing it on the phone i can’t test the code.

could any of you tell me what is wrong in my code please?

up… need help with this

You can test your code on your phone! Open Safari on your Mac and open your app afterwards. Then in Safari go to Developers -> Your phone. A debug console like Chrome´s console opens. There you can debug your code! Your phone needs to be plugged to your Mac ofc :wink: Hope this helps.

I would use destinationType : Camera.DestinationType.FILE_URL.
And using the FileTransfer plugin of cordova or http://ngcordova.com/docs/#File to upload the file.

1 Like

As per debugging You can try adding

.error(function (data, status, headers, config)  {
 alert(data, status, headers, config)
}

(alerts are not pretty I know, but they should work in Your case)

I would also suggested reading about deferred API in Angular link to Angular docs . This is what I needed to use for file upload in a web app I was building. So Your service would look something like this:

yourServices.factory('fileUpload', ['$q', '$http',
    function ($q, $http) {
        var uploadFileToUrl = function(uploadUrl) {
            var deferred = $q.defer();
            $http.post(uploadUrl).success(deferred.resolve).error(deferred.reject);

            return deferred.promise;
       }
    };

    return {
        uploadFileToUrl : uploadFileToUrl 
    };
}]
);

I would personally prefer to append the file in the controller, but that’s just my preference I think :slight_smile:

If You go on to making something bigger (with file preview etc.) I recommend this: Angular File Upload

Hope this helps!

I have this code:

$scope.takePicture = function() {
    var options = {
        quality : 80, 
        destinationType : Camera.DestinationType.FILE_URI, 
        sourceType : Camera.PictureSourceType.Camera , 
        allowEdit : true,
        encodingType: Camera.EncodingType.JPEG,
        targetWidth: 266,
        targetHeight: 266,
        popoverOptions: CameraPopoverOptions,
        saveToPhotoAlbum: false
    };

    $cordovaCamera.getPicture(options).then(function(imageData) {
        console.log(imageData);
        $scope.imageLocation = imageData;

        $cordovaFile
          .uploadFile('http://10.0.0.3:1337/file/upload', $scope.imageLocation, options)
          .then(function(result) {
            // Success! 
          }, function(err) {
            // Error
          }, function (progress) {
            // constant progress updates
          });
    });
}

Check the getPicture() function. how do i pass the key ‘avatar’ to the post and how do i pass the format of the post? and what should i put instead of the the options?

Therefore you need to set options like this:
https://github.com/apache/cordova-plugin-file-transfer/blob/master/doc/index.md#upload

ftOptions = new FileUploadOptions();

ftOptions.fileKey = 'file'; // filekey
ftOptions.fileName = params.substr(params.lastIndexOf('/') + 1); // set file name (last part of the image path)
ftOptions.mimeType = 'image/jpeg'; 
ftOptions.httpMethod = 'PUT'; // post, put...
ftOptions.headers = { }; // to set authorization headers and so on

I am having trouble getting uploads to work as well. In safari inspector I keep getting a failed to load resource error. Here is my code.

 var options = {
        quality: 50,
        destinationType: Camera.DestinationType.FILE_URL,
        sourceType: imageSource,
        allowEdit: true,
        encodingType: 0,
        targetWidth: 100,
        targetHeight: 100,
        popoverOptions: CameraPopoverOptions,
        saveToPhotoAlbum: false
        // chunkedMode: false
    };

    console.log(options);

    $cordovaCamera.getPicture(options).then(function(imageData) {
      console.log(imageData);

        var server = apiURL + '/uploads.json?' + apiKey + "&api_username=" + $rootScope.user.user.username;

        var options = {
          user_id: $rootScope.user.user.id,
          file: imageData,
          filename: imageData.substr(imageData.lastIndexOf('/')+1)
        };

        var trustAllHosts = true;
        
        $cordovaFileTransfer.upload(encodeURI(server), imageData, options, trustAllHosts)
          .then(function(result) {
          console.log('success: ' + result);
          },
          function(err) {
          // Error
            console.log('error: ' + err);
          },
          function (progress) {
          // constant progress updates
        });

        var image = document.getElementById('myImage');
        image.src = "data:image/jpeg;base64," + imageData;

        $scope.images = imageData;
        $scope.imageUrl = image.src;
        // $scope.reply.raw = '<img src=' + '"' + imageData  + '"' + ' alt="imageFromMobile">' ;
        // $scope.hideCameraActions();
    }, function(err) {
        // error
        console.log(err);
    });
}

Im not positive if I should be using the FILE_URL, or FILE_URI or base64. Thanks.

Hey i set my destinationType for the camera plugin to:
$window.navigator.camera.DestinationType.FILE_URI

Then you will get the correct file-path in your filesystem.

But if you are using ngCordova
Camera.DestinationType.FILE_URI

should do it

Because the file-transfer plugin only handles file-paths.

Another idea:
you do not set your http-method so i think it will automatically send a post request? do not know how the plugin works.
I set for the original plugin the following options:

ftOptions = new FileUploadOptions();
ftOptions.fileKey = 'file';
ftOptions.fileName = params.substr(params.lastIndexOf('/') + 1);
ftOptions.mimeType = 'image/jpeg'; (mime type of the file - if you know it)
ftOptions.httpMethod = 'PUT'; // the method your api provides for the upload (should be post or put)

i do not know if there is a matching fot those settings in ngCordova… could not find anything in their docs or maybe you can pass FileUploadOptions object directly

1 Like

Got it working. Thanks a lot @bengtler. The ngCordova docs do not include the ftOptions section. Lesson for me to always read the cordova docs first. Really appreciate the help.

Updated, working example for anyone interested. @bengtler are you using the same options and structure for Android + iOS?

var options = {
        quality: 50,
        destinationType: Camera.DestinationType.FILE_URL,
        sourceType: imageSource,
        allowEdit: true,
        encodingType: 0,
        targetWidth: 100,
        targetHeight: 100,
        popoverOptions: CameraPopoverOptions,
        saveToPhotoAlbum: false
        // chunkedMode: false
    };

    console.log(options);

    $cordovaCamera.getPicture(options).then(function(imageData) {
      console.log(imageData);

        var server = apiURL + '/uploads.json?' + apiKey + "&api_username=" + $rootScope.user.user.username;

        var trustAllHosts = true;

        var ftOptions = new FileUploadOptions();
        ftOptions.fileKey = 'file';
        ftOptions.fileName = imageData.substr(imageData.lastIndexOf('/') + 1);
        ftOptions.mimeType = 'image/jpeg';
        ftOptions.httpMethod = 'POST';

            $cordovaFileTransfer.upload(encodeURI(server), imageData, ftOptions, trustAllHosts)
              .then(function(result) {
              console.log('success: ' + angular.toJson(result));
              },
              function(err) {
              // Error
                console.log('error: ' + err);
              },
              function (progress) {
              // constant progress updates
            });

        // $scope.hideCameraActions();
    }, function(err) {
        // error
        console.log(err);
    });
}
2 Likes

This code works ?
@cpk