I'm trying to set up a PHP page that will safely accept a file upload (a resume), store it as a mysql blob, and provide a download later. But when I download the PDFs later for viewing, they always seem corrupted and won't open properly.
Thanks to a question by Jgoettsch (php: reversing mysql_real_escape_string's effects on binary), I realized that feeding the file data through mysql_real_escape_string (to prevent injection) might corrupt the file contents, and got the idea to pass the binary through base64_encode() instead, and use base64_decode() before download.
Here's some mockup code demonstrating what I'm doing currently (which is not working):
The upload:
<?
// Get file contents
$cv_pointer = fopen($_FILES['cv']['tmp_name'], 'r');
$cv_content = fread($cv_pointer, filesize($_FILES['cv']['tmp_name']));
fclose($cv_pointer);
// Insert SQL
$sql = sprintf("INSERT INTO documents (name, file, size, date_uploaded)
VALUES ('%s', '%s', '%s', NOW())",
mysql_real_escape_string($_FILES['cv']['name']),
mysql_real_escape_string($cv_content),
mysql_real_escape_string($_FILES['cv']['size']));
$result = mysql_query($sql);
?>
And the download:
<?
if (isset($_GET['view_cv'])) {
$cv = mysql_fetch_assoc($rsApplicationCv);
header("Content-length: ".$cv['size']);
header("Content-type: application/pdf");
header("Content-disposition: attachment; filename=".$cv['name']);
echo $cv['file'];
exit();
}
?>
Here are my questions:
- If you have a file upload field, is that field vulnerable to sql injection? Or am I worrying unnecessarily? Obviously this file upload task would be much simpler if I could just pass the binary to the blob field without any translations.
- If I feed the uploaded file contents through base64_encode(), is that tantamount to sanitization? or should I encode it then additionally pass the encoded string through mysql_real_escape_string?
- This all seems like a lot of effort just to store and fetch a PDF. Is there a simpler solution to this common need, that I haven't stumbled on yet?
Thanks in advance!