PHP upload-download binary files to-from mysql

This should be simple so I’m sure i’m missing something simple.

I am trying to create a few pages to upload files of different types to a myslq table and also download them. The files upload and store in the db however when I try to download them the are always corrupted.

I’ve search for half a day on google and different forums but nothing seems to work.

Magic_quotes_gpc is off as is magic_quotes_runtime. I suspect it’s uploading fine and it’s the pulling from the db/downloading that is the problem.

the MySQL table is as such:

CREATE TABLE `Files` (
  `ID` int(10) unsigned NOT NULL auto_increment,
  `Description` char(50) default NULL,
  `FileData` longblob,
  `FileName` varchar(250) default NULL,
  `FileSize` char(50) default NULL,
  `FileType` char(50) default NULL,
  PRIMARY KEY  (`ID`),
  UNIQUE KEY `ID` (`ID`),
  KEY `ID_2` (`ID`)
) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1

the upload php file:

<?PHP
$IsEdit=1;
$theme="orange";
include ("header_view.php");
?>

<form method="post" action="FileUpload_Process.php" enctype="multipart/form-data">Description:<br>
 File Description: <input type="text" name="form_description" size="40">
 <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
 <br>File to upload:<br>
 <input type="file" name="form_data" size="40">
 <p><input type="submit" name="submit" value="submit">
 </form>

 <?PHP
html_footer();
 ?>

the upload processing file:


]<?PHP
$IsEdit=1;
$theme="orange";
include ("header_view.php");
?>
<?PHP
$dbhost = '127.0.0.1';
$dbname = 'mydb';
$dbuser = 'myuser';
$dbpass = 'mypass';

$link_id = db_connect($dbhost,$dbname,$dbuser,$dbpass);
mysql_select_db($dbname, $link_id);

$FileName = $_FILES[form_data]['name'];
$tmpName = $_FILES[form_data]['tmp_name'];
$FileSize = $_FILES[form_data]['size'];
$FileType = $_FILES[form_data]['type'];

if (isset($_FILES[form_data]) && $_FILES[form_data] != "none")
{

        $content = addslashes(file_get_contents($tmpName));

             $result=MYSQL_QUERY("INSERT INTO Files (Description, FileData,FileName,FileSize,FileType)
                                    VALUES ('{$_POST[form_description]}','$content','$FileName','$FileSize','$FileType')");

             if(!$result)echo"ERROR: ".sql_error()."<BR>";
             $id= mysql_insert_id();
              print "<p>File ID: <b>$id</b><br>";
              print "<p>File Name: <b>".$_FILES[form_data]['name']."</b><br>";
              print "<p>File Name: <b>".$_FILES[form_data]['tmp_name']."</b><br>";
              print "<p>File Size: <b>".$_FILES[form_data]['size']."</b><br>";
              print "<p>File Type: <b>".$_FILES[form_data]['type']."</b><p>";
              print "To upload another file <a href=http://www.myweb.net/FileUpload.php> Click Here</a>";
              print "To download a file <a href=http://www.myweb.net/Download.php> Click Here</a>";
}
 html_footer();
 ?>

Available files list Page:


<?PHP
$IsEdit=1;
$theme="orange";
include ("header_view.php");
?>
<?PHP
$dbhost = '127.0.0.1';
$dbname = 'mydb';
$dbuser = 'myuser';
$dbpass = 'mypass';

$link_id = db_connect($dbhost,$dbname,$dbuser,$dbpass);
mysql_select_db($dbname, $link_id);

$query = "SELECT id, FileName FROM Files";
$result = mysql_query($query) or die('Error, query failed');
if(mysql_num_rows($result) == 0)
{
echo "Database is empty <br>";
}
else
{
while(list($id, $name) = mysql_fetch_array($result))
{
?>
<a href="DownloadSave.php?id=<?php echo $id;?>"><?php echo $name;?></a> <br>
<?php
}
}
?>

and finally the download page (the problem):


<?PHP
if(isset($_GET['id']))
{
$id = $_GET['id'];

$dbhost = '127.0.0.1';
$dbname = 'mydb';
$dbuser = 'myuser';
$dbpass = 'mypass';

$link_id = db_connect($dbhost,$dbname,$dbuser,$dbpass);
mysql_select_db($dbname, $link_id);

$query = "SELECT FileName, FileType, FileSize, FileData
          FROM Files WHERE id = '$id'";

$result = mysql_query($query);
if(!$result) echo "ERROR: ".$query."<BR>".sql_error()."<BR>";
list($name, $type, $size, $content) =  mysql_fetch_array($result);

header("Content-type: $type");
  header("Content-length: $size");
  header("Content-Disposition: attachment; filename=\\"$name\\"");
  header("Content-Description: PHP Generated Data");
  echo $data;

exit;
}
?>

i’ve redirected the upload page to a page that imediately returns the file instead of saving it to the database.


<?php

$FileName = $_FILES[form_data]['name'];
$tmpName = $_FILES[form_data]['tmp_name'];
$FileSize = $_FILES[form_data]['size'];
$FileType = $_FILES[form_data]['type'];

if (isset($_FILES[form_data]) && $_FILES[form_data] != "none")
{

  $content = addslashes(file_get_contents($tmpName));

  header("Content-type: $FileType");
  header("Content-length: $FileSize");
  header("Content-Disposition: attachment; filename=\\"$FileName\\"");
  header("Content-Description: PHP Generated Data");
  echo $content;

exit;
}

?>

when I upload the file, i get the save/open window prompt and if I choose open the correct app opens but reports that the data is corrupted…

so… it would appear I’m putting bad data into the database from the upload.

ideas???

ok, if I change this line

$content = addslashes(file_get_contents($tmpName));

to

$content = file_get_contents($tmpName);

then I’ve solved the corruption on upload however the insert query now fails because of the special characters…

if I change it back, the file uploads into the DB but downloads are still corrupted…

What I think I need now is a way to get the stored file from the db without PHP to check it’s integrety there… If it’s ok in the db then I’ve narrowed it down to the download script…

You should never use MySQL anymore to store file data, you should always store the file on the server using move_uploaded_file() as discussed at http://stackoverflow.com/questions/527801/php-to-store-images-in-mysql-or-not

I understand the differences between storing in blob and storing in a filesystem and the pro’s and con’s of each.

For this project it has been decided this is how we will do it so this is what I have to work with.

The amount of files will not be large nor will the size of the files.

I agree with SgtLegend… you should not really be storing files in the database.

But… as is… you should try base64 encoding. I cannot guarantee that it will work but it might save you some trouble… it basically turns binary into ascii. You would base64 encode before adding to the db and decode when downloading the file.

See http://php.net/manual/en/function.base64-encode.php

Try using mysql_real_escape_string()