1

I was wondering how I would get php script to retrieve my base64 encoded image then write to server? I tried doing a post dump from my php script and I keep getting a response that it is empty. I've tried following a few other stackoverflow guides on this but none of them use a factory afaik.

js

var app = angular.module("app", ["ui.bootstrap"]);

//http://stackoverflow.com/questions/18571001/file-upload-using-angularjs
app.factory('API', function ($http) {  
    return {
    uploadImage: function (image) {
            return $http.post('/js/upload.php', image);
    }
    }
});

app.controller('MainController',['$scope', '$http', 'API', function($scope, $http, API) {
    $scope.imageUrl = "";
    $scope.template = "";
    $scope.templates = [
    'select an option...',
    'MakeGray',
    'Canny'
    ];

    $scope.template = $scope.templates[0];

    $scope.add = function() {

    var f = document.getElementById('fileToUpload').files[0];  // name of image
    var files = document.getElementById('fileToUpload').files;
    var r = new FileReader();

    r.onload = function(event){
            console.log(event.target.result);
    }

    r.onloadend = function(e) {

            var data = e.target.result;
            var formData = new FormData();     

        $("#img1").prop("src", data);
        $("#img2").prop("src", data);

            formData.append("fileToUpload", f,f.name);

            API.uploadImage(formData)
        .success(function (imgUrl) {
            $scope.imageUrl = imgUrl;
        })
        .error (function (error) {
        });
    }

    r.readAsDataURL(f);
    }
}]);

php

<?php

if(isset($_FILES['fileToUpload'])){    
  $errors= array();        
  $file_name = $_FILES['fileToUpload']['name'];
  $file_size =$_FILES['fileToUpload']['size'];
  $file_tmp =$_FILES['fileToUpload']['tmp_name'];
  $file_type=$_FILES['fileToUpload']['type'];  
  $file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
  $extensions = array("jpeg","jpg","png");        
  if(in_array($file_ext,$extensions )=== false){
    $errors[]="image extension not allowed, please choose a JPEG or PNG file.";
  }
  if($file_size > 2097152){
    $errors[]='File size cannot exceed 2 MB';
  }              
  if(empty($errors)==true){
    move_uploaded_file($file_tmp,"../uploads/".$file_name);
    echo " uploaded file: " . "images/" . $file_name;
  }else{
    print_r($errors);
  }
}
else{
  $errors= array();
  $errors[]="No image found";
  print_r($errors);
}
?>
Zypps987
  • 404
  • 6
  • 21
  • you're not doing a file upload. you're just copying a couple bits of data out of the file input and stuffing them into a new form, without ever telling that new form that it's a file input. do a `var_dump($_POST)` and you'll probably see `fileToUpload` in there. – Marc B Dec 21 '15 at 16:19
  • I tried that in my php and I got nothing. – Zypps987 Dec 21 '15 at 16:24
  • then check `var_dump($_SERVER['REQUEST_METHOD'])`, make sure is says post. if it doesn't, then something cause a redirect. try adding a couple garbage fields to the request and see if they come through anywhere. – Marc B Dec 21 '15 at 16:25
  • the file object you trying to pass will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded" because you are not going to process file in client side, then try to disable content-type – MTroy Dec 21 '15 at 16:30
  • @Marc B I just tried var_dump($_SERVER['REQUEST_METHOD']) and got the following string(4) "POST", not sure what that means though. – Zypps987 Dec 21 '15 at 16:33
  • just means that the script was invoked as a POSt requests, which is good. there's been plenty of cases where people had a bad rewrite causing their post to be redirected into GET, which also killed everything in $_POST. – Marc B Dec 21 '15 at 16:35
  • How would I access the contents of the $_SERVER? It would appear there's 4 items, so would it be for(int i = 0; i < $_SERVER.length; i++){ echo $_SERVER.at(i); } ? I know that's not write but I'm still very new to php, I'm more familiar with c. – Zypps987 Dec 21 '15 at 16:37
  • var_dump($_SERVER);to debug, and to use: foreach($_SERVER as $key => $val) echo "$key : $val\n"; – MTroy Dec 21 '15 at 16:38
  • Here is the echo for what you just told me http://i.imgur.com/ZYj7Xpt.png The post data http://i.imgur.com/5qhT4G0.png I see that the base64 is being passed to the php, but why is it garbled garbage and not the base64 as it is shown in my javascript? How would I fix this? – Zypps987 Dec 21 '15 at 16:44
  • because your "data" variable containing base64 is not included to your FormData object, formData.append("fileToUpload", data) instead of f, but the php code is writed to a file input upload.. it will not work with base64 encoded image. (API.uploadimage is your own code ?) – MTroy Dec 21 '15 at 16:58
  • are you really need to having image base64 encoded ? why don't you use a standard input ? – MTroy Dec 21 '15 at 17:01
  • Yes, but I am very new to angularJS and webdev in general, I sort of got lucky with it working at all. – Zypps987 Dec 21 '15 at 17:02
  • I found this to be the one solution that worked vs the other ways of uploading an image with the current implementation I have with the dropdown menu. :/ if you know of a better way I'm all ears. – Zypps987 Dec 21 '15 at 17:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/98585/discussion-between-mtroy-and-zypps987). – MTroy Dec 21 '15 at 17:04

1 Answers1

0

Angular have a particularity in concern the uploading.

First, you have to kno, angular's default transformRequest function will try to serialize our FormData object, so we override it with the identity function to leave the data intact.

Next, the default content-type header for POST requests is "application/json", so you must to change this because you want to upload a file. By setting 'Content-Type': undefined, the browser sets the Content-Type to multipart/form-data himself and fills in the correct boundary. Manually setting 'Content-Type': multipart/form-data will fail to fill in the boundary parameter of the request.

Look about others possible issues : https://docs.angularjs.org/api/ng/service/$http

Now you can get you image from $_POST global array of PHP.

Fixed code

    uploadImage: function (formData)
    {
        return $http.post('js/upload.php', formData,
        {
            transformRequest: angular.identity,
            headers: {'Content-Type': undefined}
        });
    }

Note:

That the below service uses the FormData object which is not supported by IE9 and earlier.

MTroy
  • 897
  • 9
  • 20