Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

PHP Header Download Link

Status
Not open for further replies.

Kurt111780

Technical User
Nov 20, 2003
235
GB
Hello,

I have been trying to get a header download script to work so that the file path is not revealed when someone downloads a file. I found some nice code here . For some reason it didn't work so I modified it and it seems to be working in ie 6 and firefox now. Here is the code I have so far:

Code:
<?php
	$file = $_GET['fileName'];
	$path="D:\inetpub\site\php\files";

   //First, see if the file exists
   if (!is_file($file)) { die("<b>404 File not found!</b>"); }

   //Gather relevent info about file
  // $len = filesize($file);
   //$filename = basename($file);
   $file_extension = strtolower(substr(strrchr($filename,"."),1));

   //This will set the Content-Type to the appropriate setting for the file
   switch( $file_extension ) {
         case "pdf": $ctype="application/pdf"; break;
     case "exe": $ctype="application/octet-stream"; break;
     case "zip": $ctype="application/zip"; break;
     case "doc": $ctype="application/msword"; break;
     case "xls": $ctype="application/vnd.ms-excel"; break;
     case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
     case "gif": $ctype="image/gif"; break;
     case "png": $ctype="image/png"; break;
     case "jpeg":
     case "jpg": $ctype="image/jpg"; break;
     case "mp3": $ctype="audio/mpeg"; break;
     case "wav": $ctype="audio/x-wav"; break;
     case "mpeg":
     case "mpg":
     case "mpe": $ctype="video/mpeg"; break;
     case "mov": $ctype="video/quicktime"; break;
     case "avi": $ctype="video/x-msvideo"; break;

     //The following are for extensions that shouldn't be downloaded (sensitive stuff, like php files)
     case "php":
     case "htm":
     case "html":
     case "txt": die("<b>Cannot be used for ". $file_extension ." files!</b>"); break;

     default: $ctype="application/force-download";
?>

<?php
   //Begin writing headers
   header("Pragma: private");
   header("Expires: 0");
   header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  // header("Cache-Control: public");
   header("Content-Description: File Transfer");
  
   //Use the switch-generated Content-Type
   header("Content-Type: application/force-download");
   header("Content-Type: $ctype", FALSE);
   header("Content-Type: application/download", FALSE);

   //Force the download
  //$header="Content-Disposition: attachment; filename=".$filename.";";
   //header($header );
   header("Content-Disposition: attachment; filename=".basename($file));
   header("Content-Transfer-Encoding: binary");
   header("Content-Length: ".filesize($file));
   readfile("$file");
   exit;
}
?>

It works fine now but it only downloads files in the same directory as the script. How do I modify the code to use my $path variable?

Thanks,
Kurt

It's only easy when you know how.
 
I found another example here
Still same exact problem. No matter what I do jpg and exe files are corrupted. Pdf files work great.

Note in my code above this line was wrong:

Code:
$file_extension = strtolower(substr(strrchr($filename,"."),1));

supposed to be

Code:
$file_extension = strtolower(substr(strrchr($file,"."),1));

Also I had a curly brace in the wrong spot but It still has the same problem. I checked the $ctype variable and it is correct based on the file extension. Still no luck, only pdf seems to download correctly.

It's only easy when you know how.
 
I opened a jpg file with notepad and compaired it to the orginal file.
The beginning of the file had html tags! Anyone know how to fix this?

Thanks,
Kurt

It's only easy when you know how.
 
Here is the image.jpg file how its supposed to look

Code:
ÿØÿà JFIF  ` `  ÿÛ C 





#%$""!&+7/&)4)!"0A149;>>>%.DIC<H7=>;ÿÛ C

;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ÿÀ  + e" ÿÄ           	
ÿÄ µ   } !1AQa"q2?‘¡#B±ÁRÑð$3br‚	
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ        	
ÿÄ µ  w !1AQaq"2?B‘¡±Á	#3RðbrÑ
$4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚâãäåæçèéêòóôõö÷øùúÿÚ   ? “ÅZî­Š5[}NîŠPc˜€£bœcëYÛúÿ ýoÿ ïñ®Ûľð¤úó]j”ö7·¸ùÈóˆ |£'éU-¼ákØå’Ó]¼œBq(Žl²B¸Èü«U8ÛTpÎ…g&ã->g)ý¿¯ÿ Ðfÿ þÿ ?·µÿ úßÿ ßã]
x[ÁC築î;¶ù¦l&ïMØÆÕtVPË©_•#!„À‚=zSç?b~¯_ùÿ 3‰þÞ׿è3ÿ ?ÛÚ÷ý¯ÿ ïñ®™üá(ã2¶¹ä©Áœ11øÝ¿Žj{߇þÓ¬þÙy­ÞÃm€|æ›)ƒÐäbŽxö«×þÌg…&Ô/ì¦7z?üÓ	p¬gnŠÝû×üýßßöÿ «¦øOŽÕ&ÓuýLA8+Å8ÚàŽãÒ‘´-=5/ìÓâÝTÞ…ÞmÖ}ÎÔ€8æ²z½Ø'¥'©oìW_ó÷}ÿ Ûühû×üýßßöÿ Îv?ÓËøÇVi 8–5?–Œž?€^?žß@±º¶šæj†v++›?¢2 $?ŽüéZûÏüýßßöÿ >Çuÿ ?wß÷ý¿Æ³ÓKÒÞh¡-ÕÖIÈXVI
IþîTnü*k­ÊÎo&oë>nÝþZH]‚ú?ªp=Í bëú¾µá?PÅo©\H“IJm¸;ÂrGËž”VÅ¿ƒô]q
Úëwš’©òüƘ6Ò9+ÓÞŠ ŒZDño„8ü×’áCÏîýMZÓ4ÏøN¯|Mt‘Ú,ö«l–é&ö|w¹gŒÍ[ÕôK]OU°¾›S’Þ]:C$†0ƒœ‚OªÓDÈUo#F#ï†S?Àñ@Y§j¯iðÞk	ìÕlõë›V¾•·Cn]Èê9ǧl÷µãX%ð×Ã+=.ÖêF?^I®Á1óŽ€ôúßÒ|;¥iz5ƎׂöÆå?ž+–C÷Î[ ýjuŽ?¦Úè?¢\ê
¨éÌžX†îDb©ÙC oLPÜPB–ël‘¨?PF±?òíÆ1?LW›xu]ü	¯é²ƒ-…¶ªÖÖÁù/12¿A“ù×eo¦›k%±‹Ä3d]‹¹£iU}<ÃÏN2F}éfÑôâ&?it¶V«ŒY	áƒg-žr2Oz ç<7©Â!sªøVø³??7fOÍ<ß*Rãñö£C²{/Š—Bv
u6Ž²Ü8þ)^qì8Ø
énô?&ÿ UÓµ[¹"šóNÝäÈ]Fwàzu†¢]Ñ<LúøÕŸí/n-Ù7G°ÆqŒg9ïš Åðü—±ü@ñÙ!†@d¶ÝæLS»8è§5©¨i3øƒÂ—6wìºeíëeÞ3?®¯òznUâ?k Ác«ê?¾»*O¨”3ƒä•ÊŒ.Þ8©n4kkËKˆnu™ÞK‰#s8•ãØAP˜#=;š ÁoêzmÕ†Ÿã}-
›”û.«hwBÒÿ 	aÕ	þ§µ[Ôôÿ i!¼×¼:`Ôcº·šlϱ²ƒ ÆýŽCëZ—:L€‚=OWûm¼¬ËÐ;¯*X¯\qÅ;û=cÔn¯­u·…îÙZHÉ?ãÈP …=\Ð>Ö4ýnÖò[I¬îå¾Ûk2íx¦ g?\:*ö‘¦Úéßi’Þc<÷rù×3–¤|`g  ÀP	[[ÍkT¶d‚I#¸Ënrå57öM¯üð·ü–®jžÑ5+Öº»Óã’ws‚T·×f©ÂáÏú/ýüñ þÉ´ÿ žÿ ’Ñý“kÿ <-ÿ %£þ?Ð1?ïãÿ ?'ü!>ÿ  bßÇÿ  _ì›Oùáoù-Ù6ŸóÂßòZOøB|9Ÿù/ýüñ£þŸÐ1?ïãÿ ? p¾4±´µ×ü˜’,Q‰ëÍ`ýž/îÇúW«7?|0Ç-¤DÇÔ³ëIÿ …ÿ èæßãZª‰+Xá©…s“—1å_g‹û±þ”}ž/îÇúW«ÂáoúCù·øÒÂá|Ÿø“Ãù·øÓö«±R—óUöx¿»éGÙâþì¥z¯ü ~Çü?¡üÛühð¿ýáüÛühö«°}J_Ìyeœ²é×S‹9Þ1P¿–øÜ~oJ+Ö­üá¸7yzL+»å¿ÆŠÊNîçm8¸AE»ŸÿÙ

Here it is after the download

Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "[URL unfurl="true"]http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">[/URL]
<html xmlns="[URL unfurl="true"]http://www.w3.org/1999/xhtml">[/URL]
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Download Link</title>
</head>

<body>


ÿØÿà JFIF  ` `  ÿÛ C 





#%$""!&+7/&)4)!"0A149;>>>%.DIC<H7=>;ÿÛ C

;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ÿÀ  + e" ÿÄ           	
ÿÄ µ   } !1AQa"q2?‘¡#B±ÁRÑð$3br‚	
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ        	
ÿÄ µ  w !1AQaq"2?B‘¡±Á	#3RðbrÑ
$4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚâãäåæçèéêòóôõö÷øùúÿÚ   ? “ÅZî­Š5[}NîŠPc˜€£bœcëYÛúÿ ýoÿ ïñ®Ûľð¤úó]j”ö7·¸ùÈóˆ |£'éU-¼ákØå’Ó]¼œBq(Žl²B¸Èü«U8ÛTpÎ…g&ã->g)ý¿¯ÿ Ðfÿ þÿ ?·µÿ úßÿ ßã]
x[ÁC築î;¶ù¦l&ïMØÆÕtVPË©_•#!„À‚=zSç?b~¯_ùÿ 3‰þÞ׿è3ÿ ?ÛÚ÷ý¯ÿ ïñ®™üá(ã2¶¹ä©Áœ11øÝ¿Žj{߇þÓ¬þÙy­ÞÃm€|æ›)ƒÐäbŽxö«×þÌg…&Ô/ì¦7z?üÓ	p¬gnŠÝû×üýßßöÿ «¦øOŽÕ&ÓuýLA8+Å8ÚàŽãÒ‘´-=5/ìÓâÝTÞ…ÞmÖ}ÎÔ€8æ²z½Ø'¥'©oìW_ó÷}ÿ Ûühû×üýßßöÿ Îv?ÓËøÇVi 8–5?–Œž?€^?žß@±º¶šæj†v++›?¢2 $?ŽüéZûÏüýßßöÿ >Çuÿ ?wß÷ý¿Æ³ÓKÒÞh¡-ÕÖIÈXVI
IþîTnü*k­ÊÎo&oë>nÝþZH]‚ú?ªp=Í bëú¾µá?PÅo©\H“IJm¸;ÂrGËž”VÅ¿ƒô]q
Úëwš’©òüƘ6Ò9+ÓÞŠ ŒZDño„8ü×’áCÏîýMZÓ4ÏøN¯|Mt‘Ú,ö«l–é&ö|w¹gŒÍ[ÕôK]OU°¾›S’Þ]:C$†0ƒœ‚OªÓDÈUo#F#ï†S?Àñ@Y§j¯iðÞk	ìÕlõë›V¾•·Cn]Èê9ǧl÷µãX%ð×Ã+=.ÖêF?^I®Á1óŽ€ôúßÒ|;¥iz5ƎׂöÆå?ž+–C÷Î[ ýjuŽ?¦Úè?¢\ê
¨éÌžX†îDb©ÙC oLPÜPB–ël‘¨?PF±?òíÆ1?LW›xu]ü	¯é²ƒ-…¶ªÖÖÁù/12¿A“ù×eo¦›k%±‹Ä3d]‹¹£iU}<ÃÏN2F}éfÑôâ&?it¶V«ŒY	áƒg-žr2Oz ç<7©Â!sªøVø³??7fOÍ<ß*Rãñö£C²{/Š—Bv
u6Ž²Ü8þ)^qì8Ø
énô?&ÿ UÓµ[¹"šóNÝäÈ]Fwàzu†¢]Ñ<LúøÕŸí/n-Ù7G°ÆqŒg9ïš Åðü—±ü@ñÙ!†@d¶ÝæLS»8è§5©¨i3øƒÂ—6wìºeíëeÞ3?®¯òznUâ?k Ác«ê?¾»*O¨”3ƒä•ÊŒ.Þ8©n4kkËKˆnu™ÞK‰#s8•ãØAP˜#=;š ÁoêzmÕ†Ÿã}-
›”û.«hwBÒÿ 	aÕ	þ§µ[Ôôÿ i!¼×¼:`Ôcº·šlϱ²ƒ ÆýŽCëZ—:L€‚=OWûm¼¬ËÐ;¯*X¯\qÅ;û=cÔn¯­u·…îÙZHÉ?ãÈP …=\Ð>Ö4ýnÖò[I¬îå¾Ûk2íx¦ g?\:*ö‘¦Úéßi’Þc<÷rù×3–¤|`g  ÀP	[[ÍkT¶d‚I#¸Ënrå57öM¯üð·ü–®jžÑ5+Öº»Óã’ws‚T·×f©ÂáÏú/ýüñ þÉ´

It's only easy when you know how.
 
I used change it to jpeg and still have the same problem. I tried downloading a gif image and same problem. The pdf even has this html if you view the file with notepad.

Is there some directive that needs to be set? PHP is running on a windows server.

Thanks,
Kurt

It's only easy when you know how.
 
It looks to me like your script is somehow sending some HTML before it sends the file. The script you've posted, however, doesn't look like it will do that -- are you running the exact script you've posted?

Want the best answers? Ask the best questions!

TANSTAAFL!!
 
You filename should be in quotes

header("Content-Disposition: attachment; filename=\"" . $file . "\"");

Get rid of:
header("Content-Description: File Transfer");

//Use the switch-generated Content-Type
header("Content-Type: application/force-download");
header("Content-Type: application/download", FALSE);
 
I added the quotes and removed the lines as you described. The files are still getting the extra html code in ie and firefox. Here is the code again.

Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "[URL unfurl="true"]http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">[/URL]
<html xmlns="[URL unfurl="true"]http://www.w3.org/1999/xhtml">[/URL]
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Download Links</title>
</head>
<body>
<?php
    $file = $_GET['fileName'];
    $path="D:\inetpub\site\php\files";

   //First, see if the file exists
   if (!is_file($file)) { die("<b>404 File not found!</b>"); }

   //Gather relevent info about file
  // $len = filesize($file);
   //$filename = basename($file);
   $file_extension = strtolower(substr(strrchr($file,"."),1));

   //This will set the Content-Type to the appropriate setting for the file
   switch( $file_extension )
   {
     case "pdf": $ctype="application/pdf"; break;
     case "exe": $ctype="application/octet-stream"; break;
     case "zip": $ctype="application/zip"; break;
     case "doc": $ctype="application/msword"; break;
     case "xls": $ctype="application/vnd.ms-excel"; break;
     case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
     case "gif": $ctype="image/gif"; break;
     case "png": $ctype="image/png"; break;
     case "jpeg":
     case "jpg": $ctype="image/jpg"; break;
     case "mp3": $ctype="audio/mpeg"; break;
     case "wav": $ctype="audio/x-wav"; break;
     case "mpeg":
     case "mpg":
     case "mpe": $ctype="video/mpeg"; break;
     case "mov": $ctype="video/quicktime"; break;
     case "avi": $ctype="video/x-msvideo"; break;

     //The following are for extensions that shouldn't be downloaded (sensitive stuff, like php files)
     case "php":
     case "htm":
     case "html":
     case "txt": die("<b>Cannot be used for ". $file_extension ." files!</b>"); break;

     default: $ctype="application/force-download";
	}
?>
<?php
   //Begin writing headers
   header("Pragma: private");
   header("Expires: 0");
   header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  // header("Cache-Control: public");
  // header("Content-Description: File Transfer");
  
   //Use the switch-generated Content-Type
   //header("Content-Type: application/force-download");
   header("Content-Type: $ctype");
  // header("Content-Type: application/download", FALSE);

   //Force the download
  //$header="Content-Disposition: attachment; filename=".$filename.";";
   //header($header );
   //header("Content-Disposition: attachment; filename=".basename($file));
   header("Content-Disposition: attachment; filename=\"" . $file . "\""); 
   header("Content-Transfer-Encoding: binary");
   header("Content-Length: ".filesize($file));
   @readfile("$file");
   exit;
?>
</body>
</html>

It's only easy when you know how.
 
well of course they are? You are kicking out a header before the file is sent..

header MUST MUST be the first thing output by PHP. which means you need to get rid of

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "<html xmlns="<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Download Links</title>
</head>
<body>

and every other html in that php document.
 
Your code

should be

Code:
<?php
    $file = $_GET['fileName'];
    $path="D:\inetpub\site\php\files";

   //First, see if the file exists
   if (!is_file($file)) { die("<b>404 File not found!</b>"); }

   //Gather relevent info about file
  // $len = filesize($file);
   //$filename = basename($file);
   $file_extension = strtolower(substr(strrchr($file,"."),1));

   //This will set the Content-Type to the appropriate setting for the file
   switch( $file_extension )
   {
     case "pdf": $ctype="application/pdf"; break;
     case "exe": $ctype="application/octet-stream"; break;
     case "zip": $ctype="application/zip"; break;
     case "doc": $ctype="application/msword"; break;
     case "xls": $ctype="application/vnd.ms-excel"; break;
     case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
     case "gif": $ctype="image/gif"; break;
     case "png": $ctype="image/png"; break;
     case "jpeg":
     case "jpg": $ctype="image/jpg"; break;
     case "mp3": $ctype="audio/mpeg"; break;
     case "wav": $ctype="audio/x-wav"; break;
     case "mpeg":
     case "mpg":
     case "mpe": $ctype="video/mpeg"; break;
     case "mov": $ctype="video/quicktime"; break;
     case "avi": $ctype="video/x-msvideo"; break;

     //The following are for extensions that shouldn't be downloaded (sensitive stuff, like php files)
     case "php":
     case "htm":
     case "html":
     case "txt": die("<b>Cannot be used for ". $file_extension ." files!</b>"); break;

     default: $ctype="application/force-download";
    }

   //Begin writing headers
   header("Pragma: private");
   header("Expires: 0");
   header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  // header("Cache-Control: public");
  // header("Content-Description: File Transfer");
  
   //Use the switch-generated Content-Type
   //header("Content-Type: application/force-download");
   header("Content-Type: $ctype");
  // header("Content-Type: application/download", FALSE);

   //Force the download
  //$header="Content-Disposition: attachment; filename=".$filename.";";
   //header($header );
   //header("Content-Disposition: attachment; filename=".basename($file));
   header("Content-Disposition: attachment; filename=\"" . $file . "\""); 
   header("Content-Transfer-Encoding: binary");
   header("Content-Length: ".filesize($file));
   @readfile("$file");
   exit;
?>
 
OMG, finally it works, thank you. I thought I tried removing the html but I still had other commented out php before the script, which must of causing file corruption also.

My original question, How would I modify the script to use the $path variable?

Thanks for your help,
Kurt

It's only easy when you know how.
 
$file = "D:/inetpub/site/php/files/" . $_GET['fileName'];


make sure to use basename($file) for your header info
 
I strongly recommend that the script NOT use $_GET['fileName'] without checking it first.

For example, how would the previously-posted code react to a filename containing one or more "../" ?

Want the best answers? Ask the best questions!

TANSTAAFL!!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top