Page 1 of 1

PHP code for downloading a ZIP

Posted: Sat Jan 26, 2008 2:31 pm
by tarview
Well, last time I had an issue and posted here, it fixed itself, so maybe it'll happen again.

I'm trying to add code to let the visitor download a ZIP file, then show some HTML follow-up. Here's what I'm trying:

Code: Select all

<?php
...
header( "Content-type: application/x-zip-compressed" );
header( "Content-Disposition: attachment; filename='example.zip'" );
readfile( "source.zip" );
?>
<html>
...
</html>
Now, I realize that it's recommended (maybe required?) to put in "Content-length", but then I can't add the HTML (unless I add the length of the HTML to content-length, maybe). But that's not the issue.

Instead of downloading the ZIP, it displays the contents in raw text form. This happens whether or not I include Content-length. The only difference then is whether it shows the follow-up HTML.

I've tried other MIME types, too, including
applicaton/zip
multipart/zip
application/octet-stream

All give the same result. I've even tried excluding the Content-type header altogether to see if PHP could figure it out.

Is there maybe a server setting that I'm not aware of? My gut tells me it has to do with either the MIME type or readfile. If so, what's the alternative?

This is a hosted account, so I don't have root access. Also, it's PHP4.

(Just refreshed and still not working. Maybe after I hit submit...)

Re: PHP code for downloading a ZIP

Posted: Sat Jan 26, 2008 2:43 pm
by JAM
You cant show html (or code) after the download is triggered. The download must then be called upon using javascript, ajax (same thing basicly) or by using iframes or similiar solutions.

Other than that, here are some ideas for headers to use (for a rar file, but still):

Code: Select all

    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-Type: application/x-rar-compressed");
    header("Content-Disposition: attachment; filename=foo.rar;");
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize("foo.rar"));
    @readfile("foo.rar");

Re: PHP code for downloading a ZIP

Posted: Sat Jan 26, 2008 5:33 pm
by tarview
Thank you! I can live without the HTML follow-up (sent the info in an e-mail), so this works out fine. 8)

Re: PHP code for downloading a ZIP

Posted: Sat Jan 26, 2008 7:22 pm
by John Cartwright
JAM wrote:You cant show html (or code) after the download is triggered. The download must then be called upon using javascript, ajax (same thing basicly) or by using iframes or similiar solutions.

Other than that, here are some ideas for headers to use (for a rar file, but still):

Code: Select all

    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-Type: application/x-rar-compressed");
    header("Content-Disposition: attachment; filename=foo.rar;");
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize("foo.rar"));
    @readfile("foo.rar");
I believe the filename attribute in the content disposition header is required to be quoted.

Code: Select all

   header("Content-Disposition: attachment; filename=\"foo.rar;\"");

Re: PHP code for downloading a ZIP

Posted: Sat Jan 26, 2008 8:04 pm
by JAM
Good catch, missed that one. :teach:

Re: PHP code for downloading a ZIP

Posted: Sat Jan 26, 2008 8:38 pm
by Chris Corbyn
Jcart wrote:I believe the filename attribute in the content disposition header is required to be quoted.

Code: Select all

   header("Content-Disposition: attachment; filename=\"foo.rar;\"");
Actually it's not ;) It's required to be a valid "phrase" but if it hasn't got any spaces (or special characters) in it then it doesn't need the quotes ;)

PS: Move the semi-colon in your code outside of the double quotes...

Re: PHP code for downloading a ZIP

Posted: Sat Jan 26, 2008 8:45 pm
by JAM
Chris Corbyn wrote:Actually it's not ;) It's required to be a valid "phrase" but if it hasn't got any spaces (or special characters) in it then it doesn't need the quotes ;)

PS: Move the semi-colon in your code outside of the double quotes...
Actually II, according to the rfc (1806 and 2616) it should. :D
filename-parm = "filename" "=" quoted-string
It seldom breaks so noone really tend to care. not even part of the http/1.1 standards.

Re: PHP code for downloading a ZIP

Posted: Sat Jan 26, 2008 8:53 pm
by Chris Corbyn
JAM wrote:
Chris Corbyn wrote:Actually it's not ;) It's required to be a valid "phrase" but if it hasn't got any spaces (or special characters) in it then it doesn't need the quotes ;)

PS: Move the semi-colon in your code outside of the double quotes...
Actually II, according to the rfc (1806 and 2616) it should. :D
filename-parm = "filename" "=" quoted-string
It seldom breaks so noone really tend to care. not even part of the http/1.1 standards.
I concede :oops: I assumed the MIME implementation would match that of RFC 2045's Content-Disposition spec.

EDIT | Or whichever RFC that header is defined in for mail. Grrr... too many dman RFC's :P

Here's RFC 2045's definition of a parameter:

Code: Select all

parameter := attribute "=" value
 
     attribute := token
                  ; Matching of attributes
                  ; is ALWAYS case-insensitive.
 
     value := token / quoted-string
 
     token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
                 or tspecials>

Re: PHP code for downloading a ZIP

Posted: Sat Jan 26, 2008 9:02 pm
by Chris Corbyn
Ah, so RFC 1806 is what I was thinking of correctly, but RFC 2616 ammends that syntax for HTTP for some reason. I wonder why that is.

EDIT | I'll let it drop swear :P Just checking RFC 2183, which replaces 1806 and the syntax for the value remained the same there too. Ok, I'm done, but confused :lol: