For security reasons I’ve decided that uploading user profile images to a database, rather than just a folder and uploading the image addresses, would be a good idea.
I’ve never dealt with file uploads in a backend before, but having read up about this from various sources, I believe that I’m doing everything correctly. However no useful binary data is being uploaded.
in php.ini
file_uploads=On
In the frontend
<form enctype="multipart/form-data" method="post" autocomplete="on" action="upload/"> <p> <input type="file" id="avatar" name="avatar" accept="image/png, image/jpeg" required /> <label for="avatar">*Profile photo</label> </p> <p class="submitter two-thirds columns"> <input type="submit" value="Apply" /> </p> </form>
In the backend
if(isset($_SESSION['id'])) $UserID = $_SESSION['id']; else exit(1); if (!empty($_FILES['avatar'])){ $photo = fopen($_FILES['avatar']["tmp_name"], 'rb'); $photo_mime = $_FILES['avatar']["type"]; } else exit(1); $values_data = array( $UserID, $photo, $photo_mime, ); $sql = "INSERT INTO `user` ( UserID, photo, photo_mime ) VALUES ( :UserID, :photo, :photo_mime ) ON DUPLICATE KEY UPDATE photo = :photo, photo_mime = :photo_mime "; $sth = $dbh->prepare($sql); $sth->bindValue(':UserID', $values_data[0]); $sth->bindValue(':photo', $values_data[1]); $sth->bindValue(':photo_mime', $values_data[2]); $sth->execute();
And the database does get some information
However those image binaries are all 1KB. Looking inside them they have data that is like this
Resource id #13
So the binaries are getting messed up or dropped somewhere along the line… but where?
Advertisement
Answer
fopen()
doesn’t return the contents of the file. It returns a file pointer resource, which you then can pass to something like fread() to get the contents.
Something like:
$handler = fopen($_FILES['avatar']["tmp_name"], 'r'); $file = fread($handler, filesize($_FILES['avatar']["tmp_name"])); fclose($handler);
An easier way would be to use file_get_contents():
$file = file_get_contents($_FILES['avatar']["tmp_name"]);
which will give you the contents in one line.