Search code examples
javascriptangularjsionic-frameworkng-file-upload

ngFileUpload on safari posts empty file


Im using ngFileUpload to send images to cloudinary service, my app is build on ionic and is intended to run on ios and android, I have the following code to upload images:

.service('photoUploadService', ['$q','Upload', '$ionicLoading', 'AppModel',
	function($q, $upload, $ionicLoading, AppModel){
    // creating a return object with a data property, matching the structure we return from the router resolve
    var ref = this;

    ref.dataURItoBlob = function(dataURI) {
		var contentType = 'image/png';
	  	var sliceSize = 512;

	  	var byteCharacters = atob(dataURI.split(',')[1]);
		  var byteArrays = [];

		  for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
		    var slice = byteCharacters.slice(offset, offset + sliceSize);

		    var byteNumbers = new Array(slice.length);
		    for (var i = 0; i < slice.length; i++) {
		      byteNumbers[i] = slice.charCodeAt(i);
		    }

		    var byteArray = new Uint8Array(byteNumbers);

		    byteArrays.push(byteArray);
		  }
		    
		  var blob = new Blob(byteArrays, {type: contentType});
		  return blob;
	};

    ref.uploadPhoto = function(imageData, waitMessage, sucessCallback, sucessCBParameters){
    	var deferred = $q.defer();

    	var filename = Math.floor(Math.random()*90000) + 10000 + ".png";
		//var imageBase64 = finalAd.ad.image.split(',')[1];
		var blob = ref.dataURItoBlob(imageData);//new Blob([imageBase64], {type: 'image/png'});
		var file = new File([blob], filename, {type: 'image/png'});
		
		file.upload = $upload.upload({
			url: "https://api.cloudinary.com/v1_1/xxxxx/upload",
			data: {
				upload_preset: "xxxxx",
				tags: 'myphotoalbum',
				context: 'photo=' + filename,
				file: file
			}
		}).progress(function (e) {
			file.progress = Math.round((e.loaded * 100.0) / e.total);
			file.status = "Uploading... " + file.progress + "%";
			$ionicLoading.show({template: waitMessage + (file.progress) + "%"});
		}).success(function (data, status, headers, config) {
            sucessCBParameters.data = data;
            sucessCallback(sucessCBParameters);
            deferred.resolve(AppModel.ad.ad);
            
        }).error(function (data, status, headers, config) {
        	file.result = data;
        	console.error('PENDING ERROR HANDLER');
        	deferred.reject(data);
        });
        return deferred.promise;
    };
}]);

When I run my code under android, it works flawlessly and the images the uploaded to the server, but running on IOs I get an "Empty File" error back from cloudinary. Debugging the code, the file seems to be created correctly and the only error I'm getting is "Empty file".

So far I haven't been able to identify were the actual problem is, if it's with ngFileUpload or the way I'm creation the image fiel.

So far I've tried the steps described in this posts looking at a poss Convert base64 data url to image file in angularjs Convert base64 data image file in angularjs and http://ourcodeworld.com/articles/read/150/how-to-create-an-image-file-from-a-base64-string-on-the-device-with-cordova with no luck.

Any help would be appreciated.


Solution

  • For anyone else with this problem, ng-file-upload cannot be used along with cordova, here the original answer ng-file-upload not uploading in Ionics

    In case someone else needs the code to easily upload pictures to cloudinary, this is the one that is working for me.

    ref.uploadPhoto = function(imageData, album, waitMessage, imgType){
        var deferred = $q.defer();
        var filename = Math.floor(Math.random()*90000) + 10000 + ".png";
        var options = {
            fileName: filename,
            chunkedMode: false,
            mimeType: "image/png",
            params: {'upload_preset': "XXXXX",
                    'tags': album,
                    'context': 'photo=' + filename},
    
        };
    
        $cordovaFileTransfer.upload("https://api.cloudinary.com/v1_1/XXXXX/upload",
            imageData, options)
            .then(function(result){
                var response = JSON.parse(result.response);
                response.type = imgType;
                deferred.resolve(response);
            }, function(err){
                console.error(err);
                deferred.reject(err);
            }, function(progress){
                var val = Math.round(((progress.loaded * 100.0) / progress.total));
                console.log(val);
                if(waitMessage){
                    $ionicLoading.show({template: waitMessage + val + "%"});    
                }
            }).catch(function(err){
                console.error(err);
                deferred.reject(err);  
            });
    
        return deferred.promise;
    };