tags:

views:

58

answers:

5

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;   
+2  A: 

//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.

sheeks06
Also, the OP should use [`readfile`](http://php.net/readfile), which is much more efficient.
deceze
I removed the comment and it's still empty. Actually I have been using file_get_contents($filename); for quite sometime already and it worked fine that's why I guess there's no problem for this part of the code.
anonymous123
`file_get_contents()` will cause your script to die if the file being loaded is larger than the PHP `memory_limit` setting (it tries to slurp the entire file into memory in one shot). `readfile()` avoids this by internally reading the file sequentially in small chunks and sending them individually.
Marc B
edited my answer. read the comments to this answer for more info.
sheeks06
+1  A: 

Try

header("Content-type: application/octet-stream");
chakrit
+1  A: 

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;
}
Johnus
Yeah! I mean any type of file from admin/ folder only.
anonymous123
A: 

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?

deceze
A: 

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');
?> 
Jet