mikeg542 Posted January 20, 2009 Share Posted January 20, 2009 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; Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 20, 2009 Share Posted January 20, 2009 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; Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 20, 2009 Author Share Posted January 20, 2009 If I do it with a .doc file for example, the file displays pages of failed to display characters instead of the 5 letters the document actually has. It does seem to be keeping the extension better however! Just another problem came out of that Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 20, 2009 Share Posted January 20, 2009 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. Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 20, 2009 Author Share Posted January 20, 2009 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. Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 20, 2009 Share Posted January 20, 2009 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; Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 20, 2009 Author Share Posted January 20, 2009 It got rid of all the stuff within the file. Entirely. Images still dont keep their extensions. Otherwise it's mkaing quite a bit of progress, thanks! Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 20, 2009 Share Posted January 20, 2009 wow...just realized...where is $link getting set in the upload script? Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 20, 2009 Author Share Posted January 20, 2009 Right above the section I give. It's just a random num/letter generator (8 characters from A-Z, a-z and 0-9). Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 20, 2009 Share Posted January 20, 2009 cus you are using that value for the filename when someone is downloading Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 21, 2009 Author Share Posted January 21, 2009 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; } Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 21, 2009 Share Posted January 21, 2009 what is the purpose of $link? to make a unique filename? Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 21, 2009 Author Share Posted January 21, 2009 $link is used as a unique identifier that users can use to upload a certain file. While we trust all the users with uploading and downloading, we still only want those who are supposed to get the files to be able to open them (thus the lnik codes) Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 21, 2009 Share Posted January 21, 2009 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? Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 21, 2009 Author Share Posted January 21, 2009 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. Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 21, 2009 Share Posted January 21, 2009 sorry, but that is the wrong way to do it. in download.php you should check to see if the user has access to the requested file. the way you have it now, you can easily have collisions with the $linknum and overwrite files Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 21, 2009 Author Share Posted January 21, 2009 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 Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 21, 2009 Share Posted January 21, 2009 ok...moving on to fixing the code then, what field in your table do you store the name of the file? all i see is linknum...there needs to be a field to keep the original filename Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 21, 2009 Author Share Posted January 21, 2009 Currently I just have it using the linknum as the file name, but you are correct that I should have a proper name. I don't think it effects the code working though. Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 21, 2009 Share Posted January 21, 2009 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 Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 21, 2009 Author Share Posted January 21, 2009 According to the code the file gets uploaded as /uploads/$link Wouldn't that make it: readfile('uploads/'.$name); works? Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 21, 2009 Share Posted January 21, 2009 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" Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 21, 2009 Author Share Posted January 21, 2009 Ok, it has a name now. How would that change the readfile() code? (if at all) Not keeping their extensions means it is being saved as type 'file' and won't open in any picture viewer. Quote Link to comment Share on other sites More sharing options...
rhodesa Posted January 21, 2009 Share Posted January 21, 2009 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; } Quote Link to comment Share on other sites More sharing options...
mikeg542 Posted January 21, 2009 Author Share Posted January 21, 2009 It's aparently not downloading any of the files currently. If I download it, it has 0 bytes of data in it. The name thing is working though Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.