Download Docs

Hi,

I have uploaded ms word docs and pdfs to my site.

How do I use PHP to allow user to open files from my site? They click on a link and the file should open in either MS Word or Adobe Reader.

How do I use headers for this?

header("Content-type: application/pdf");

Thanks.

Take a look at [fphp]readfile[/fphp]

The header you have there is okay, but you might want to add a Content-Disposition to force browser to download the file, rather than show it inline.


header("Content-type: application/pdf"); 
header("Content-Disposition: attachment"); 
readfile("/path/to/my/file.pdf");

Thanks.
Have the below code. But I want to read files from 2 different directories. How do I set the correct filepath based on which file the user clicked?


$path = "/documents/policy/"; // change the path to fit your websites document structure
$fullPath = $path.$_GET['download_file'];

if ($fd = fopen ($fullPath, "r")) 
{
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-type: application/pdf"); // add here more headers for diff. extensions
header("Content-Disposition: attachment; filename=\\"".$path_parts["basename"]."\\""); // use 'attachment' to force a download
break;
case "doc":
header("Content-type: doc"); // add here more headers for diff. extensions
header("Content-Disposition: attachment; filename=\\"".$path_parts["basename"]."\\""); // use 'attachment' to force a download
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\\"".$path_parts["basename"]."\\"");
}
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly

while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
exit;

Thanks!

2 different directories how? one for pdf and one for doc? in that case you need to set the path in the switch, not before it.

BTW. You have a huge security hole in there. Consider this


yourdownloader.php?file=../../etc/passwd

That is the code I have been getting online.

This is the actual download link code…


					 // load available files
					 $current_dir = 'documents/education/';
          if ($handle = opendir($current_dir)) 
					{
					 	  $i=0;
              while (false !== ($file = readdir($handle))) 
							{
                  if ($file != "." && $file != "..") 
									{
									 	 $files[$i] = $file;
										 $i++;
                  }
              }
              closedir($handle);
          }	
					sort($files);
					
          for($i=0; $i<sizeof($files); $i++)
          {
           				$currentfile = $current_dir.rawurlencode($files[$i]);		
          				//echo $currentfile;
                  //echo '<li><a href='.$currentfile.'>'.$files[$i].'</a></li>';
                  echo '<li><a href=education.php?download_file='.$currentfile.'>'.$files[$i].'</a></li>';
          }

And the updated header code, which I got from php manual


$file = $_REQUEST['download_file']; // documents/education/test.docx

echo 'FILE:'.$file;

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}

$file is blank. Why is this?

Does it show a value in the HTML? If so maybe $_REQUEST doesn’t work as expected on your host; try $_GET (which is more appropriate than $_REQUEST anyway).

Also tried $_GET but nothing shown.

The link is now…
mysite.com/home/education.php?documents/education/test.docx

OK. This is my entire code education.php. I would be very grateful if you could point where I am going wrong.
Thanks!


<?php
session_start();

$file = $_GET['download_file']; // documents/education/test.docx

//echo 'FILE:'.$file;
ECHO $_GET['download_file'];

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />

</head>
<body>


<div id="mainContent">

<h1>Education</h1>

<?php
				
echo '<p>Available Documents:</p>';
echo '<ul>';

// load available files
$current_dir = 'documents/education/';
if ($handle = opendir($current_dir)) 
{
$i=0;
while (false !== ($file = readdir($handle))) 
{
if ($file != "." && $file != "..") 
{
$files[$i] = $file;
$i++;
}
}
closedir($handle);
}	

sort($files);
					
for($i=0; $i<sizeof($files); $i++)
{
$currentfile = $current_dir.rawurlencode($files[$i]);		
echo $currentfile;
//echo '<li><a href='.$currentfile.'>'.$files[$i].'</a></li>';
echo '<li><a href=education.php?download_file='.$currentfile.'>'.$files[$i].'</a></li>';
}
							echo '</ul>';

?>	
	
</div> <!-- #end mainContent-->

That href needs quoting


echo '<li><a href="education.php?download_file='.$currentfile.'">'.$files[$i].'</a></li>';

Have you thought about how to solve that massive security hole yet?

Ensure proper database login? Is my script fine otherwise?

Yes your script looks fine otherwise. Ensuring a database login will help, but not secure it in the best way (because you’re hiding it, rather than really securing it). What you want is


$file=ltrim($_GET['download_file'], './');

:slight_smile: