File's uploaded to MySQL DB are corrupting.

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
impulse()
Forum Regular
Posts: 748
Joined: Wed Aug 09, 2006 8:36 am
Location: Staffordshire, UK
Contact:

File's uploaded to MySQL DB are corrupting.

Post by impulse() »

Everytime I upload a file to a MySQL in mediumblob format it downloads corrupt. The file size of the file that is downloaded is the correct file size of the file I uploaded the the DB. Can anybody see problems with this code:

This uploads the file:

Code: Select all

$fileName = $_FILES['userfile']['name'];
    $fileType = $_FILES['userfile']['type'];
    $tempName = $_FILES['userfile']['tmp_name'];
    $fileErro = $_FILES['userfile']['error'];
    $fileSize = $_FILES['userfile']['size'];

    $fp       = fopen($tempName, 'r');
    $content  = fread($fp, fileSize($tempName));
    $content  = addslashes($content);
    fclose($fp);

    if(!get_magic_quotes_gpc()) {
      $fileName = addslashes($fileName);
    }

    include_once("x");

    $query = "INSERT INTO upload (name, type, size, content)
            VALUES ('$fileName', '$fileType', '$fileSize', '$content')";
    mysql_query($query, $conn) or die (mysql_error());
This downloads the file:

Code: Select all

$id = $_GET["id"];

    $query = mysql_query("SELECT name, type, size, content
                          FROM upload
                          WHERE id = '$id'");

    while ($res = mysql_fetch_array($query)) {

      header("Content-length: ". $res['size']);
      header("Content-type: ". $res['type']);
      header("Content-Disposition: attachment; filename = ". $res['name']);
      echo $res['content'];
Regards,
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

why don't you just store the file in your filesystem and then in the database store a path to the file? Makes more sense to me.
impulse()
Forum Regular
Posts: 748
Joined: Wed Aug 09, 2006 8:36 am
Location: Staffordshire, UK
Contact:

Post by impulse() »

I have no plans to make use of storing data at the moment. I just wanted to learn how storing data in a MySQL DB worked.
nickvd
DevNet Resident
Posts: 1027
Joined: Thu Mar 10, 2005 5:27 pm
Location: Southern Ontario
Contact:

Post by nickvd »

What is the data-type of the field that the content is going into?
impulse()
Forum Regular
Posts: 748
Joined: Wed Aug 09, 2006 8:36 am
Location: Staffordshire, UK
Contact:

Post by impulse() »

Mediumblob
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Post by pickle »

A couple things (perhaps off topic):

- Rather than fopen(), blah, blah, blah, you could use file_get_contents(). 3 lines down to 1.
- Rather than addslashes(), use mysql_real_escape_string().

Now, as for your actual question:
- Right now you're adding slashes on the insert, but not removing them when you take them out. Using mysql_real_escape_string() I believe will get around that & you'll have clean content pulled out of the DB. Test that though - I'm not 100% sure.
- How do you know the file is 'corrupt'?
- Download Firefox (if you haven't already) & install the Firebug plugin. That will allow you to directly see the headers that are sent. Perhaps they're not formed as well as you think.
- If you're downloading this file as an attachment (which I've always used if I want to force the user to download the file as opposed to just open it), you don't need to specify the Content-type.
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
impulse()
Forum Regular
Posts: 748
Joined: Wed Aug 09, 2006 8:36 am
Location: Staffordshire, UK
Contact:

Post by impulse() »

pickle wrote:A couple things (perhaps off topic):

- Rather than fopen(), blah, blah, blah, you could use file_get_contents(). 3 lines down to 1.
- Rather than addslashes(), use mysql_real_escape_string().

Now, as for your actual question:
- Right now you're adding slashes on the insert, but not removing them when you take them out. Using mysql_real_escape_string() I believe will get around that & you'll have clean content pulled out of the DB. Test that though - I'm not 100% sure.
- How do you know the file is 'corrupt'?
- Download Firefox (if you haven't already) & install the Firebug plugin. That will allow you to directly see the headers that are sent. Perhaps they're not formed as well as you think.
- If you're downloading this file as an attachment (which I've always used if I want to force the user to download the file as opposed to just open it), you don't need to specify the Content-type.
I tried escaping the data as it was retrieved from the database but I still have the same results. I've tried uploading and downloading a zip file, a jpeg and an Exe but all fail to open. Winrar reports with the zip file that the file is "corrupt", the jpeg fails to load an image and the exe only has a DOS icon for it. The files are the correct sizes though. Here is the full code I've used, sorry for the following spam:

Code: Select all

echo "<a href = 'upload.php?action=upload'> Upload </a>
      <a href = 'upload.php?action=download'> Download </a>";


if ($_GET["action"] == "upload") {

?>
<br><br>
<form method = 'post' enctype = 'multipart/form-data'>
<br><input type = 'hidden' name = 'MAX_FILE_SIZE' value = '2000000'>
<br><input name = 'userfile' type = 'file' id = 'userfile'>
<br><input name = 'upload' type = 'submit' class = 'box' id = 'upload' value = 'Upload'>
</form>

<?php

  if (isset($_POST["upload"]) && $_FILES['userfile']['size'] > 0) {

    echo "<table>";

    foreach($_FILES['userfile'] as $key => $value) {

      echo "<tr> <td> $key </td> <td> $value </td> </tr>";

    }

    echo "</table>";

    $fileName = $_FILES['userfile']['name'];
    $fileType = $_FILES['userfile']['type'];
    $tempName = $_FILES['userfile']['tmp_name'];
    $fileErro = $_FILES['userfile']['error'];
    $fileSize = $_FILES['userfile']['size'];

    $fp       = fopen($tempName, 'r');
    $content  = fread($fp, fileSize($tempName));
    $content  = addslashes($content);
    fclose($fp);

    echo "Filename: $fileName<br>
          FileType: $fileType<br>
          FileSize: $fileSize<br>";


    if(!get_magic_quotes_gpc()) {
      $fileName = addslashes($fileName);
    }

    include_once("/etc/sqlConn/connect.php");

    $query = "INSERT INTO upload (name, type, size, content)
            VALUES ('$fileName', '$fileType', '$fileSize', '$content')";
    mysql_query($query, $conn) or die (mysql_error());

    echo "File uploaded";
  }
}

  if  ($_GET["action"] == "download") {

    include_once("/etc/sqlConn/connect.php");

    $query = mysql_query("SELECT *
                          FROM upload");
    $i = 0;
    while ($res = mysql_fetch_array($query)) {

      $tempHoldID[$i] = mysql_real_escape_string($res['id']);
      $tempHold[$i]   = mysql_real_escape_string($res['name']);
      $tempHoldID[$i] = stripslashes($tempHoldID[$i]);
      $tempHold[$i]   = stripslashes($tempHold[$i]);
      $i++;
    }

    for ($i = 0; $i < count($tempHold); $i++) {
      echo "<a href = 'upload.php?id=$tempHoldID[$i]'> $tempHold[$i] </a> <br>";
    }

}


  if (isset($_GET['id'])) {

    include_once("/etc/sqlConn/connect.php");

    $id = $_GET["id"];

    $query = mysql_query("SELECT name, type, size, content
                          FROM upload
                          WHERE id = '$id'");

    while ($res = mysql_fetch_array($query)) {

      header("Content-length: ". mysql_real_escape_String($res['size']));
      header("Content-type: ". mysql_real_escape_string($res['type']));
      header("Content-Disposition: attachment; filename = ". mysql_real_escape_string($res['name']));
      echo mysql_real_escape_string($res['content']);

    }

    exit;
}

Can you suggest something else to try?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Are you aware of all the negatives associated with storing binary data in a database such as MySQL?
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Is magic_quotes_runtime on? Uploaded files may be full of slashes and you may need to use stripslashes. I forget which magic_quotes_* affects what requests/data, but try stripslashes() while you're reading the file contents just to check. Or upload a plain-text file with " and ' and \ characters in it then open it yourself and see if extra slashes were added.

EDIT | Why are you using mysql_real_escape_string() in header()? That will cause problems, you only want to use that whilst running queries. Which you are NOT. That's bad, you're wide open to attack.
Post Reply