Reputation: 851
How can I download files(text/pdf/etc) using php with a header that pops-up in order for the user to choose Save or Open? The file is stored in (admin/)
I'm using this but it won't work. The downloaded file is empty! Here's my code:
//get the filename
$filename = $_GET['filename'];
//open the file based in filename and path
$fp = fopen('admin/'.$filename, 'w') or die("can't open file");
header("Content-type: text/pdf");
header("Content-Disposition: attachment; filename=file.txt");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
//echo file_get_contents($filename);
exit;
Upvotes: 0
Views: 4944
Reputation: 18958
//echo file_get_contents($filename);
Is this really supposed to be commented out?
Edited:
And use readfile
The reason why you can see ANYTHING is because your not showing ANYTHING after the header declaration.
Upvotes: 3
Reputation: 1325
I think this code would solve your problem.
<?php
$allowed_files = array('filename1.pdf', 'filename2.pdf'); //list content allowed files
$file = $_GET["file"];
if(in_array($file , $allowed_files)) {
header("Content-type: text/pdf");
header("Content-Disposition: attachment; filename=file.txt");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
readfile($file);
exit;
}
else die('you do not have permission to download this file');
?>
Upvotes: 0
Reputation: 522510
Some problems:
$filename = $_GET['filename'];
$fp = fopen('admin/'.$filename, 'w') or die("can't open file");
What if I use /page.php?filename=../../../../list_of_secret_passwords
? This is called a directory traversal attack, something you need to protect against. Furthermore, you don't need to open a file handle (with write access no less), just use file_exists
or is_readable
to check if the file exists.
//echo file_get_contents($filename);
If this line is commented out, of course nothing will happen. You should first and foremost use readfile
though. file_get_contents
will read the entire file into memory, then echo
it like a regular string. This is hugely wasteful and might crash your script for large files. readfile
outputs the file directly to the user output, using almost no extra memory.
This is probably your real problem though:
/* $fp = fopen( */ 'admin/'.$filename /* , 'w') or die("can't open file"); */
/* echo file_get_contents( */ $filename /* ); */
'admin/'.$filename
vs. $filename
Which one is it?
Upvotes: 0
Reputation: 720
This sounds like a dangerous thing you are attempting. Why do you want the user to be able to download any file? Are you sure you don't want them to just be able to download files in a certain directory? With your script they could have access to all your PHP scripts and potentially find security loopholes in your server.
Also, with the commented out line, you might consider replacing it with a less memory intensive solution
while ($fp !== false && ($file_contents_buffer = fgets($fp, 10000)) !== false) {
echo $file_contents_buffer;
}
Upvotes: 0