Angular, PHP, and File Uploads
After having to take a few weeks off from development of my website, Iâm happy to say that Iâm back...and running headfirst into massive snags.
Iâve managed to connect Angularjs and MySQL with PHP after a long and protracted battle. Â I can now create articles/blog posts that have titles, dates, authors, and actual body content (though Iâve not gotten around to fetching it to display yet - thatâs coming up).
Angularjs doesnât really play well with FILE uploads - in my case I really want my beautiful blog to have header images...and itâs not really worked out well so far.
Upload a header image at the same time as the title/body of the blog but have the image go into my server file structure while only retaining a url for the purposes of the mysql database (itâs a bad idea to store images inside a database).
It seems that angular http.post doesnât allow you to just plain old pass through a file, meaning that the only way to do this would be to have angular convert the image into something else. Â After a lot of research (going on 10 hours or so probably) Iâve figured out a solution - I think. Â There we some shortcuts (downloading premade angular controllers & services) but as that wouldnât really have TAUGHT me anything (which is the primary goal of this exercise) I chose to ignore them aside from looking through the code for ideas.
The (potential) solution:
HTML5! Â I know, after all this work with php and javascript itâs weird to find a solution inside HTML of all things (at least it was to me), but there you have it.
Hereâs my upload controller as it currently stands.
(function() {
var UploadController = function($scope, $http, $location) { //scope lets me pull stuff from the html, http lets me do a post pass to php, and location lets me redirect afterwards.
$scope.upload = function() {
var x;
  var file = document.getElementById('blogheader').files[0], //javascript to pull out the FILE
    reader = new FileReader(); //html5 filereader to convert it into base64
  reader.onloadend = function(event){
  x = event.target.result.match(/,(.*)$/)[1]; //here's my actual base64 result and a regex to discard things that get in the way.
  $http.post('../../php/upload.php', { // this is my php file for the actual upload.
'posttitle': $scope.posttitle, // passing post title...
'postcontent': $scope.postcontent, // passing post content...
'blogheader': x // passing blog header!
})
.success(function(data) {
console.log(data); //Just used for debugging purposes to see what PHP returns, will get rid of this later.
$location.url('/'); // redirect to homepage after blog is submitted.
})
.error(function(data, status) {
console.log(data, status); Â //just used for debugging.
});
 Â
  }
  reader.readAsDataURL(file); // calling the html5 reader for the conversion.
};
};
.controller('UploadController', UploadController);
UploadController.$inject = ['$scope', '$http', '$location']; //this is a property of angularjs used to avoid getting your code broken by minify. Â I have this in all my controllers.
angular.module('myApp')
}());
<div ng-controller="UploadController">
<img ng-src="images/photos/{{windowSize}}/egypt-soccer-{{windowSize}}.jpg" alt="Soccer on the Nile" class="image__main">
<form name="submitForm" enctype="multipart/form-data" class="login__fields" method="post" novalidate ng-submit="upload()">
<input type="text" ng-model="posttitle" name="posttitle" placeholder="enter title here" required>
<br />
<textarea ng-model="postcontent" name="postcontent" placeholder="enter text here" required></textarea>
<br />
<input type="file" id="blogheader" name="blogheader" required>
<br />
<input type="submit" name="submit" value="Upload" ng-disabled="!submitForm.$valid">
</form>
</div>
And finally where my PHP currently stands (not finished yet):
$postdata = json_decode(file_get_contents("php://input"));
$posttitle = mysqli_real_escape_string($link, $postdata->posttitle);
$postcontent = mysqli_real_escape_string($link, $postdata->postcontent);
$blogheader = $postdata->blogheader;
echo base64_decode($blogheader);
Decode the json that Iâm getting from angularjs and putting it into $postdata - NOTHING WILL WORK WITHOUT THIS
Assigning $posttitle, $postcontent, and $blogheader to their relevant POST-passed values.
Echoing the base64_decoded value of the $blogheader (image) to see where Iâm at.
Getting blog posts into mysql (again), but this time also uploading the image to my server and getting the relevant url into the blog table.