Get a picture, upload it to the server


#1

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?


#2

up… need help with this


#3

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.


#4

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.


#5

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!


#6

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?


#7

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

#8

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.


#9

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


#10

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);
    });
}

Doubt about how to upload and download files from a server
#11

This code works ?
@cpk