Jump to content

Files downloaded from database corrupt/not keeping file extension


mikeg542

Recommended Posts

As the title suggests, I am storing files in the database then having others download them. When the file downloads, firefox knows what the file type is (example txt, pdf, jpeg) but when it is installed on my computer it doesn't have the file extension nor can it be opened by the applicable viewing application. Here's my code:

 

upload file

$fileName = $_FILES['userfile']['name'];

$tmpName  = $_FILES['userfile']['tmp_name'];

$fileSize = $_FILES['userfile']['size'];

$fileType = $_FILES['userfile']['type'];

 

$fp      = fopen($tmpName, 'r');

$content = fread($fp, filesize($tmpName));

$content = addslashes($content);

fclose($fp);

 

 

$query = "INSERT INTO items (sizefile, typefile, content, linknum, sentstaffid, recievedstaffid, clientname) ".

"VALUES ('$fileSize', '$fileType', '$content', '$link', '', '', '')";

 

 

Downloading the file:

while(list($id) = mysql_fetch_array($result))

{

?>

<a href="download.php?id=<?=$id;?>"><?=$id;?></a> <br>

<?php

}

}

}

 

 

download.php

include (databaseopen.php);

 

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

{

$id = $_GET['id'];

$query = "SELECT linknum, typefile, sizefile, content FROM items WHERE linknum = '$id'";

 

$result = mysql_query($query) or die('Error, query failed' . mysql_error());

list($name, $type, $size, $content) = mysql_fetch_array($result);

$content = stripslashes($content);

 

header("Content-type: $type");

header("Content-length: $size");

header("Content-Disposition: attachment; filename=$name");

header("Content-Description: PHP Generated Data");

echo $content;

 

 

exit;

Link to comment
Share on other sites

is this MySQL? change the following lines:

 

update file:

    $fileName = mysql_real_escape_string($_FILES['userfile']['name']);
    $tmpName  = mysql_real_escape_string($_FILES['userfile']['tmp_name']);
    $fileSize = mysql_real_escape_string($_FILES['userfile']['size']);
    $fileType = mysql_real_escape_string($_FILES['userfile']['type']);

    $fp      = fopen($tmpName, 'r');
    $content = fread($fp, filesize($tmpName));
    $content = mysql_real_escape_string($content);
    fclose($fp);


    $query = "INSERT INTO items (sizefile, typefile, content, linknum, sentstaffid, recievedstaffid, clientname) ".
    "VALUES ('$fileSize', '$fileType', '$content', '$link', '', '', '')";

 

download.php

include (databaseopen.php);

if(isset($_GET['id']))
{
$id = $_GET['id'];
$query = "SELECT linknum, typefile, sizefile, content FROM items WHERE linknum = '$id'";

$result = mysql_query($query) or die('Error, query failed' . mysql_error());
list($name, $type, $size, $content) = mysql_fetch_array($result);
//$content = stripslashes($content);

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


exit;

Link to comment
Share on other sites

hum...ok...try doing base64 encode/decode...

update file

    $fileName = mysql_real_escape_string($_FILES['userfile']['name']);
    $tmpName  = mysql_real_escape_string($_FILES['userfile']['tmp_name']);
    $fileSize = mysql_real_escape_string($_FILES['userfile']['size']);
    $fileType = mysql_real_escape_string($_FILES['userfile']['type']);

    $fp      = fopen($tmpName, 'r');
    $content = fread($fp, filesize($tmpName));
    $content = base64_encode($content);
    fclose($fp);

    $query = "INSERT INTO items (sizefile, typefile, content, linknum, sentstaffid, recievedstaffid, clientname) ".
    "VALUES ('$fileSize', '$fileType', '$content', '$link', '', '', '')";

 

download.php

include (databaseopen.php);

if(isset($_GET['id']))
{
$id = $_GET['id'];
$query = "SELECT linknum, typefile, sizefile, content FROM items WHERE linknum = '$id'";

$result = mysql_query($query) or die('Error, query failed' . mysql_error());
list($name, $type, $size, $content) = mysql_fetch_array($result);
$content = base64_decode($content);

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


exit;

 

to be honest...databases aren't really for storing files. you should keep the files in a folder somewhere. once you insert the record into the database (do everything the same, except don't put the content in), use mysql_insert_id() to get the ID of that row. Then, move the file to the folder and name it that ID.

 

Link to comment
Share on other sites

same problem. The document gets filled with crap.

 

The purpose for this script is for authenticated users (these are going to be people who we trust to directly upload the files) will upload the files and this will create a linknum that can be entered in a field to download the file from the website with the same linknum. If this could be done without needing to store the files like this, That'd work perfectly well too. Thanks for your help thus far.

Link to comment
Share on other sites

yeah, create a folder, let's call it 'uploads'. put this folder outside the webroot or use htaccess to block direct access to it. in your table, i assume you have a unique field? you mention linknum, so i will assume this field is unique:

 

    $fileName = mysql_real_escape_string($_FILES['userfile']['name']);
    $fileSize = mysql_real_escape_string($_FILES['userfile']['size']);
    $fileType = mysql_real_escape_string($_FILES['userfile']['type']);

    $query = "INSERT INTO items (sizefile, typefile, content, linknum, sentstaffid, recievedstaffid, clientname) ".
    "VALUES ('$fileSize', '$fileType', '', '$link', '', '', '')";

    $tmpName  = $_FILES['userfile']['tmp_name'];
    move_uploaded_file($tmpName,'uploads/'.$link);

that should move the file to the uploads folder (change the path to uploads accordingly). and the filename should be whatever the value of $link is (again, which i assume is unique)

 

then to download:

include (databaseopen.php);

if(isset($_GET['id']))
{
$id = mysql_real_escape_string($_GET['id']);
$query = "SELECT linknum, typefile, sizefile FROM items WHERE linknum = '$id'";

$result = mysql_query($query) or die('Error, query failed' . mysql_error());
list($name, $type, $size) = mysql_fetch_array($result);

header("Content-type: $type");
header("Content-length: $size");
header("Content-Disposition: attachment; filename=$name");
header("Content-Description: PHP Generated Data");
readfile('uploads/'.$name);
exit;

Link to comment
Share on other sites

Here's what I have now

 

upload

if (isset($_POST['upload']))

{

$linkchars = 'BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz123456789';

$link = '';

for ($x=0; $x < 8; $x++)

{

$link .= $linkchars{rand(0, strlen($linkchars)-1)};

}

    $fileName = mysql_real_escape_string($_FILES['userfile']['name']);

    $fileSize = mysql_real_escape_string($_FILES['userfile']['size']);

    $fileType = mysql_real_escape_string($_FILES['userfile']['type']);

 

    $query = "INSERT INTO items (sizefile, typefile, content, linknum, sentstaffid, recievedstaffid, clientname) ".

    "VALUES ('$fileSize', '$fileType', '', '$link', '', '', '')";

 

    $tmpName  = $_FILES['userfile']['tmp_name'];

    move_uploaded_file($tmpName,'uploads/'.$link);

 

mysql_query($query) or die('Error, query failed:'. mysql_error());

 

 

download

 

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

{

 

$id = mysql_real_escape_string($_GET['id']);

$query = "SELECT linknum, typefile, sizefile FROM items WHERE linknum = '$id'";

 

$result = mysql_query($query) or die('Error, query failed' . mysql_error());

list($name, $type, $size) = mysql_fetch_array($result);

 

header("Content-type: $type");

header("Content-length: $size");

header("Content-Disposition: attachment; filename=$name");

header("Content-Description: PHP Generated Data");

readfile('uploads/'.$name);

 

exit;

}

 

 

 

 

Link to comment
Share on other sites

but the link is just a random 8 characters right? so there is a unique key for it? instead, you should have an auto_increment field in your table. you insert the row into the table, then use that to identify it. do you have an auto_incrementing primary key?

Link to comment
Share on other sites

I do, but since the linknum can be fed into download.php?id=##. If it just uses an autoincrementer, each user would have access to their file as well as every single one before it in the increment.

 

Having the link my way gives : 51^8 possibilities which makes it HIGHly unlikely to have a non-unique code. As well, there will be a function that checks if the code is taken when it is created.

Link to comment
Share on other sites

Not particularly, the chances are still 1 in hundreds of thousaunds that two are the same even with 10000 entries. But that's not the point, I was told to do it this way so I'm just doing the best I can with what I have (validation with the database to redo the $link = ... if there already is one with that name).

I just hope to figure out why the doc files are empty and the image files are not keeping their extensions. I appreciate any help you give

Link to comment
Share on other sites

right, but we are past that...

 

when downloading, you want the filename to be the original filename when it was uploaded right?

 

-a user uploads sample.doc

-it generates a random linknum: abcdefgh

-the user goes to download.php?id=abcdefgh

-the file that downloads should be called sample.doc right?

 

if so, you need to store the filename "sample.doc" into a field in the DB

Link to comment
Share on other sites

right...that is the internal path to the file...but i'm talking about the headers you send to the person downloading it:

 

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

 

$name is whatever filename you want in the Save prompt the user gets. i assume that is what you meant by "not keeping their extensions". if i am wrong what do you mean by "not keeping their extensions"

Link to comment
Share on other sites

assuming the new field is called 'namefile':

 

if (isset($_POST['upload']))
{
  $linkchars = 'BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz1234567 89';
  $link = '';
  for ($x=0; $x < 8; $x++)
  {
    $link .= $linkchars{rand(0, strlen($linkchars)-1)};
  }

  //Move file
  $tmpName  = $_FILES['userfile']['tmp_name'];
  move_uploaded_file($tmpName,'uploads/'.$link);
  
  //Add to database     
  $fileName = mysql_real_escape_string($_FILES['userfile']['name']);
  $fileSize = mysql_real_escape_string($_FILES['userfile']['size']);
  $fileType = mysql_real_escape_string($_FILES['userfile']['type']);
  $query = "INSERT INTO items (sizefile, typefile, namefile, linknum, sentstaffid, recievedstaffid, clientname) VALUES ('$fileSize', '$fileType', '$fileName', '$link', '', '', '')";
  mysql_query($query) or die('Error, query failed:'. mysql_error());
}

 

if(isset($_GET['id']))
{
  $id = mysql_real_escape_string($_GET['id']);
  $query = "SELECT linknum, typefile, sizefile, namefile FROM items WHERE linknum = '$id'";
  $result = mysql_query($query) or die('Error, query failed' . mysql_error());
  list($file, $type, $size, $name) = mysql_fetch_array($result);

  header("Content-type: $type");
  header("Content-length: $size");
  header("Content-Disposition: attachment; filename=$name");
  header("Content-Description: PHP Generated Data");
  readfile('uploads/'.$file);
  exit;
}

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.