arrgh!!

i am getting nutz about that: i want to force a file to download after someone hits my flashbutton, which opens the forcing php-file.
i thought this should work

<?php
		// required for IE, otherwise Content-disposition is ignored
		if(ini_get('zlib.output_compression'))
		  ini_set('zlib.output_compression', 'Off');
		
		// addition by Jorg Weske
		$file_extension = strtolower(substr(strrchr($filepath,"."),1));
		echo "&bestaetigung=MIME:".$file_extension." \n&";
		
		if( $filepath == "" ) 
		{
		  echo "...";
		  exit;
		} elseif ( ! file_exists( $filepath ) ) 
		{
		  echo "...File not found";
		  exit;
		};
		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;
		  default: $ctype="application/force-download";
		}
		header("Pragma: public"); // required
		header("Expires: 0");
		header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
		header("Cache-Control: private",false); // required for certain browsers 
		header("Content-Type: ".$ctype);
		
		// change, added quotes to allow spaces in filenames, by Rajkumar Singh

                // The following lines where not commented out in the post originally
                // I added the comments so the lines would show.  Norton was blocking them: nevets

		//header("Content-Disposition: attachment; filename=\"".basename($filepath)."\";";
		////header("Content-Transfer-Encoding: binary");
		//header("Content-Length: ".filesize($filepath));
		//readfile($filepath);
		//exit();

?>

and i don't find another way to force some downloads...
any help???

thanx!

[Edited to add <code> and </code> tags: nevets]

Comments

headkit’s picture

somebody was telling me that this should work

header("Location: ".$url);

which is much shorter...

but nothing works!!
aarrgh!

by the way: where is the big difference between the long and the short method?

nevets’s picture

What do you mean by force a file for download? Do you mean so the broswer popups the "save as" dialog or I you trying to avoid the dialog (which you are not supposed to be able to do)?

headkit’s picture

the popup would be wunderfull!

zbricoleur’s picture

...you want a file to download when a link is clicked, instead of opening in the browser window.

If that is correct, this works well for me.

Create a file called download.php, and put this in it:

<?php
$file = $_GET['file'];
header ("Content-type: octet/stream");
header ("Content-disposition: attachment; filename=".$file.";");
header("Content-Length: ".filesize($file));
readfile($file);
exit;
?>

Then make your link like this: http://www.example.com/download.php?file=myfile.pdf (where 'myfile.pdf' is replaced with the name of your file, obviously). Note that for the script to work as written, the file to be downloaded needs to be in the same directory as download.php.

Depending on the browser and its settings, this will either open a dialog box that prompts the user to save, or just open the file in its native application (instead of in the browser). I believe in the latter case it also forces a download.

headkit’s picture

hm, the thing is that i use a flash application to force the download via php.
that should be no problem for me but perhaps this changes the point of vew of the script i activate?

your skrit looks like the one i posted with less header-parameters. but i try that. perhaps this works.
thank you!

headkit’s picture

hm, does not work.
perhaps because i develop on localhost?

zbricoleur’s picture

"develop on localhost." I suppose you could develop Flash locally without even having a Web server installed. My solution (not mine, actually, but I've forgotten where I learned it) requires a Web server with PHP installed...if you try it that way, I'm pretty sure it will work.

headkit’s picture

slow down. its just a flash button inside a drupal page.

zbricoleur’s picture

Assuming you have Drupal installed in the root directory of www.example.com, you've:

a) Put download.php in that directory.
b) Put the file to be downloaded in that directory.
c) Linked to http://www.example.com/download.php?file=name-of-file with your button.

headkit’s picture

the trick should be not to show the file path at all. the flashbutton tells the php which FID has do be downloaded.

zbricoleur’s picture

<?php
$fileid = $_GET['FID'];
switch ($fileid) {
case 0:
    $filename = "mypdf0.pdf";
    break;
case 1:
    $filename = "mypdf1.pdf";
    break;
case 2:
    $filename = "mypdf2.pdf";
    break;
}
header ("Content-type: octet/stream");
header ("Content-disposition: attachment; filename=".$filename.";");
header("Content-Length: ".filesize($file));
readfile($file);
exit;
?>
nevets’s picture

I found using IIS under Windows that the download never produces the popup window as expected.

zbricoleur’s picture

I'm on a WinIIS server as well, and it appears to depend on the browser (as I noted above). It pops up a dialog box for me in Firefox; in Safari it just opens the file in the default application for the file type.

headkit’s picture

so on a provided server with linux it will work?

Spiceworm’s picture

Yes, it forces the download.
But the name of the file that you are downloading is download.php. Is there any way to set this name?

I'm using it to force download of a GPX file (gps data in xml format) and most browsers just display it.
I can tell the user to right click, and than select "save as..." but in ie 6.0 the extension is renamed to .xml. The intended userbase of the site won't understand how to change.

Thanks for any help, i've lost almost a day with this.

zbricoleur’s picture

My understanding of the different headers is rudimentary; I just cadged the original of that script from http://www.sometricks.com/2006/04/23/download-pdf-jpg-gif-directly-from-...

I did a little poking around, though, out of a desire to learn more, and you may be out of luck for IE5.5 anyway: http://support.microsoft.com/kb/281119/EN-US/

The Content-disposition header tells the browser to open a dialog box offering to save the file. It's up to the browser to interpret that correctly and apparently some don't.

On the other hand, GPX is not (to my knowledge) a known MIME type, so the browser may, in fact, be interpreting the header correctly: http://support.microsoft.com/kb/260519
In that case, you may have to live with the .xml extension.

Maybe someone who actually knows will come along and correct me...

PaulWood’s picture

zbricoleur,

I'm using your download.php code; however the open/download dialog always shows "download.php" as the file to be opened/downloaded, not "myfile.pdf" (i.e. the filname I've included after the "?file="). The file in question is located in the same directory as download.php.

----------------------------------

Edit: When I remove .htaccess from the directory, it works just fine. However, I'm afraid to remove .htaccess because I don't know what security implications would result. Contents of .htaccess:

SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
Options None
Options +FollowSymLinks

----------------------------------

Edit again (in case someone else has the same problem): Changed .htaccess to the following and all is well!

SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
< Files download.php>
SetHandler None
< /Files>
Options None
Options +FollowSymLinks

Note: Ignore the space inserted after the <. Had to add it to get the line to display here.

shaneforsythe’s picture

That code snippet is a classic example of http://en.wikipedia.org/wiki/Directory_traversal exploit

Which leads to something like this,
http://www.example.com/download.php?file=../../../../../../../../../etc/...

diamondsea’s picture

Please don't ever simply read in a file from a URL-provided string. This would let people download ANY file on your system that they want by putting the URL-Encoded path in the URL, eg:

http://www.example.com/download.php?file=%2Fetc%2Fpasswd

Which would give the random internet user your /etc/passwd file.

Always sanitize and sanity-check your inputs, and never trust any outside data.

Mark Theunissen’s picture

Was looking for help on this and found the following module which works nicely:

http://drupal.org/project/file_force

Hope that helps!

__________________________________________________________

Mark Theunissen

(work) Digital People
(personal) Code Baboon

shriji’s picture

joining...

kbk’s picture

I needed to do this with csv files and, following this site, I added this line to the .htaccess file found within the core directory:

AddType application/octet-stream .csv