Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to initiate a download?

On a PHP-based web site, I want to send users a download package after they have filled out a short form. The site-initiated download should be similar to sites like download.com, which say "your download will begin in a moment."

A couple of possible approaches I know about, and browser compatibility (based on a quick test):

1) Do a window.open pointing to the new file.

- FireFox 3 blocks this.  
 - IE6 blocks this.  
 - IE7 blocks this.

2) Create an iframe pointing to the new file.

- FireFox 3 seems to think this is OK. (Maybe it's because I already accepted it once?)  
 - IE6 blocks this.  
 - IE7 blocks this.

How can I do this so that at least these three browsers will not object? 

Bonus: is there a method that doesn't require browser-conditional statements?

(I believe that download.com employs both methods conditionally, but I can't get either one to work.)

Responses and Clarifications:

Q: "Why not point the current window to the file?"  
A: That might work, but in this particular case, I want to show them some other content while their download starts - for example, "would you like to donate to this project?"

UPDATE: I have abandoned this approach. See my answer below for reasons.

like image 620
Nathan Long Avatar asked Sep 13 '08 15:09

Nathan Long


3 Answers

You can also do a meta refresh, which most browsers support. Download.com places one in a noscript tag.

<meta http-equiv="refresh" content="5;url=/download.php?doc=123.zip"/>
like image 175
Soldarnal Avatar answered Oct 20 '22 18:10

Soldarnal


Update: I have decided to abandon this approach, and instead just present the user with a link to the actual file. My reasoning is this:

My initial attempts at a server-initiated download were blocked by the browser. That got me thinking: "the browser is right. How does it know that this is a legitimate download? It should block a download that isn't obviously user-initiated."

Any method that I can use for a server-initiated download could also be used by someone who wants to send malware. Therefore, downloads should only happen when the user specifically requests the file by clicking on a link for it.

You're free to disagree, and if you still want to initiate a download, hopefully this thread will help you do it.

like image 43
Nathan Long Avatar answered Oct 20 '22 18:10

Nathan Long


I usually just have a PHP script that outputs the file directly to the browser with the appropriate Content-Type

if(file_exists($filename)) {
    header("Pragma:  public");
    header("Expires:  0");
    header("Cache-Control:  must-revalidate, pre-check=0");
    header("Cache-Control:  private", false);
    header("Content-Type:  " . $content-type);
    header("Content-Disposition:  attachment; filename=\"" . basename($filename) . "\";" );
    header("Content-Transfer-Encoding:  binary");
    header("Content-Length:  " . filesize($filename));

    readfile("$filename");
}else{
    print "ERROR:  the file " . basename($filename) . " could not be downloaded because it did not exist.";
}

The only disadvantage is that, since this sets the HTTP header, it has be called before you have any other output.

But you can have a link to the PHP download page and it will cause the browser to pop up a download box without messing up the content of the current page.

like image 40
Mark Biek Avatar answered Oct 20 '22 18:10

Mark Biek