Page 1 of 1
File's uploaded to MySQL DB are corrupting.
Posted: Thu Feb 22, 2007 3:43 pm
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,
Posted: Thu Feb 22, 2007 3:50 pm
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.
Posted: Thu Feb 22, 2007 4:00 pm
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.
Posted: Thu Feb 22, 2007 4:08 pm
by nickvd
What is the data-type of the field that the content is going into?
Posted: Thu Feb 22, 2007 4:21 pm
by impulse()
Mediumblob
Posted: Thu Feb 22, 2007 5:18 pm
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.
Posted: Mon Feb 26, 2007 6:12 pm
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?
Posted: Mon Feb 26, 2007 7:57 pm
by feyd
Are you aware of all the negatives associated with storing binary data in a database such as MySQL?
Posted: Tue Feb 27, 2007 12:59 am
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.