Download script problem

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
werlop
Forum Commoner
Posts: 68
Joined: Sat Mar 22, 2003 2:50 am
Location: /dev/null

Download script problem

Post by werlop »

I have been trying to make a download script, and from sticking together various posts in this forum, I have made a solution that works but is by no means perfect, the problem is that all files are always called download.extension, eg download.gif, download.pdf. I would like the file to be called its real file name.

The script I have made is below:

Code: Select all

<?php
<?php
	
	/*
	
	BAnet Module
	============
	
	Name: Downloads
	Last Modified: 29/7/03
	Last Modified By: David Brooks
	Purpose: To list and give files available for download
	
	*/

	// If the user has clicked on a download button include the config file, as the 
	// page is being called independantly of index.php
	if ( isset ( $_POST["path"] ) AND isset ( $_GET["downloadid"] ) ) {
		include( "./config.php" );
		}	// End of IF
	
	$db = connect_to_database();	// Connect to the database
	
	if ( isset ( $_POST["path"] ) AND isset ( $_GET["downloadid"] ) ) {		// Start the download process if the user has clicked on a button

		$mimetype=exec("file -i -b " . SERVER_PATH . $filename);	// Get the mime type for the download
		
		// Make up the download directory
		$fileDir = FULL_PATH; 
		$fileName = $_POST["path"]; 
		$completeFilePath=$fileDir.$fileName; 

		// IE cannot download without a cache, so clear these headers 
		if(strpos($HTTP_SERVER_VARS['HTTP_USER_AGENT'], 'MSIE')){ 
		   header("Pragma: "); 
		   header("Cache-Control: "); 
		} 
		else { //prevent caching 
		   header('Pragma: no-cache'); 
		   header('Cache-Control: no-cache, must-revalidate'); 
		} // End of else case
		
		// Send the headers
		header("Content-Type: $mimetype"); 
		header("Content-Disposition: attachment; filename=".$fileName); 
		header("Content-Length: ".filesize("$completeFilePath")); 

		// Open the file, and set a pointer (read and binary mode)
		$fn=fopen($completeFilePath,'rb'); 

		// To save RAM, buffer the file as it is sent
		while(!feof($fn)) { // this replacement for fpassthru uses less memory (for large files) 
  			$buffer = fread($fn, 4096); 
  			print $buffer; 
		}	// End of while loop
		
	$file_to_download = doSQL( "SELECT * FROM downloads WHERE id = " . $_GET["downloadid"], $db );
	
	while ( $data = mysql_fetch_array( $file_to_download ) ) {
		$count = $data["downloads"];
		} // End of while loop
		
	$downloads = $count + 1;
	
	$update = doSQL( "UPDATE `downloads` SET `downloads` = '$downloads' WHERE `id` = '$_GET[downloadid]'" , $db );
	
	mysql_free_result( $file_to_download );
	mysql_free_result( $update );
	
	} else {	// If the user is not downloading a file, then go here

?>

<link href="nav.css" rel="stylesheet" type="text/css"> 
<table width="100%" border="0" cellpadding="4" cellspacing="0">
  <!--DWLayoutTable-->
  <tr> 
    <td height="45" valign="middle" class="header">Downloads <img src="img/small_pdf_icon.gif"><img src="img/word_icon.jpg" width="30" height="29"> 
      <img src="img/excel_icon.jpg" width="34" height="30"></td>
  </tr>
  <tr> 
    <td valign="top" class="body"> 
      <blockquote> 
        <p>This section of the site lists all documents that are available to 
          download. BAnners are not listed here, to get a BAnner, click on the 
          BAnner link on the left hand side. The following files may vary in size, 
          so download times will also vary, however, nothing will take an inordinate 
          amount of time.</p>
        <p>Some files may require Adobe Acrobat (.pdf)<img src="img/small_pdf_icon.gif">to 
          view. This can be downloaded from <a href="http://www.adobe.com" target="_blank">www.adobe.com</a>. 
          Some files may require require Microsoft Office to view or another program.</p>
        <p>Click on the button beside the file you want to download. Note, the 
          downloaded file will be called download, if you want to download more 
          than one file of the same type, you may have to rename files.</p>
      </blockquote></td>
  </tr>
</table>

<p>&nbsp;</p>
<table width="100%" border="0" cellspacing="0" cellpadding="4">
  <!--DWLayoutTable-->
  <tr> 
    <td width="10%" valign="top"><!--DWLayoutEmptyCell-->&nbsp;</td>
    <td width="30%" valign="top" class="bodybold">Name of File</td>
    <td width="25%" valign="top" class="bodybold">Type</td>
    <td width="25%" valign="top" class="bodybold">Size of File</td>
    <td width="10%" valign="top" class="bodybold">Downloads</td>
  </tr>
  <tr> 
    <td height="4" colspan="5" valign="top"></td>
  </tr>
<?php

	$all_downloads = doSQL( "SELECT * FROM downloads ORDER BY id DESC", $db );
	
	while ( $data = mysql_fetch_array( $all_downloads ) ) {
		$id = $data["id"];
		$name = $data["name"];
		$path = $data["path"];
		$type = $data["type"];
		$count = $data["downloads"];
		
		$size = round ( ( filesize( $path ) / 1024 ), 2 ) . " Kb";
?>
  <tr> 
    <td width="10%" valign="top"><form name="form1" method="post" action="<?php print SERVER_PATH; ?>include/download.php?downloadid=<?php print $id; ?>">
        <input type="hidden" name="path" value="<?php print $path; ?>">
        <input name="Download" type="submit" id="Download" value="Download">
      </form></td>
    <td width="30%" valign="top" class="body"><?php print $name; ?></a></td>
    <td width="25%" valign="top" class="body"><?php print $type; ?></td>
    <td width="25%" valign="top" class="body"><?php print $size; ?></td>
    <td width="10%" valign="top" class="body"><?php print $count; ?></td>
  </tr>
<?php 
	} // End of while
mysql_free_result( $all_downloads );
} // End of IF
mysql_close( $db );
?>
</table>

?>
If the user has not clicked on a download button, this page is included as part of the website, if the user clicks the download button then the top part is executed, and this script (download.php) is run independantly of index.php (the file that includes this page. This page is in a directory called /includes

The custom MySQL functions are definied in config.php, the relevant parts to this being:

Code: Select all

<?php
	// Define website constants
	define("FULL_PATH", "G:/Program Files/Apache Group/Apache2/htdocs/ba/");		// Full path to site on server
	define("SERVER_PATH", "/ba/");		// Relative path to site from document root
	define("SITE_URL", "http://localhost/ba");		// Full site url
?>

and

Code: Select all

<?php
// Function connects to the database based on the defined constants and returns the result, also outputs errors
// To call: $db = connect_to_database();

function connect_to_database() {
	
	
	$db = mysql_connect(DATA_HOST, DATA_USER, DATA_PASS)
		or die ("Error, could not connect to the database, please contact the school and inform them of this error. MySQL provided the following error: ".mysql_error() );
	
	mysql_select_db(SITE_DB,$db)
		or die ("Couldn't open database $db: ".mysql_error() );

	return $db;	// return the result
	
}
	
	
// Same as mysql_query(), but has error handling, to call: $whatever = $doSQL("SQL query string", $db);
// Call connect_to_database first	

function doSQL($sql,$db) {
		
		$result = mysql_query("$sql",$db) or die("Error<br><hr>".mysql_error());
		
		return $result;
		
}
?>
Any help on how to make the download not be called download.extension would be appreciated!

Thanks in advance!
User avatar
patrikG
DevNet Master
Posts: 4235
Joined: Thu Aug 15, 2002 5:53 am
Location: Sussex, UK

Post by patrikG »

What's the value for $fileName = $_POST["path"]?
I suppose it comes from the hidden input-field in script 1 but it's not clear what value it has.
If necessary, do a

Code: Select all

echo "<pre>";
print_r($_POST);echo "</pre>";
at the top of script 1.
User avatar
werlop
Forum Commoner
Posts: 68
Joined: Sat Mar 22, 2003 2:50 am
Location: /dev/null

Post by werlop »

Hi, yes $_POST["path"] comes from the hidden field an example of what appears when I try your suggestion is:

Array
(
[path] => img/go.gif
[Download] => Download
)


i should point out that all these folders are stored in a folder SERVER_ROOT/ba eg SERVER_ROOT/ba/img

the script i posted is in SERVER_ROOT/ba/includes/download.php

the FULL_PATH constant that I am using is the actual path to the file on the server (G:/Program Files/Apache Group/Apache2/htdocs/ba/), I am doing this so I can easily change the site from development mode (Windows) to production mode (linux).

This problem is not essential, as the file still downloads, but it is annoying that everything is called download.whatever, and I would like to find a solution. Incidentally is what I have done correct? Until last night I had never worked with files or headers.

Thanks in advance.
User avatar
werlop
Forum Commoner
Posts: 68
Joined: Sat Mar 22, 2003 2:50 am
Location: /dev/null

Post by werlop »

You can see for yourself by going to http://80.5.108.150/ba

Once you are there, click on the downloads link.
User avatar
werlop
Forum Commoner
Posts: 68
Joined: Sat Mar 22, 2003 2:50 am
Location: /dev/null

Post by werlop »

Does anybody else have any other ideas?
jmarcv
Forum Contributor
Posts: 131
Joined: Tue Jul 29, 2003 7:17 pm
Location: Colorado

Post by jmarcv »

All I do is <a href=thefile.whatever>Download</a>
Why go through agony?
Post Reply