HTTP Headers for ZIP File Downloads
You know when you you’re working on a project and get stuck on something, so you scour the Web for solutions only to find that everyone else seems to be experiencing the exact same thing. Then, after many hours trying everything possible, you finally stumble onto something that seems to work. This time, the project was setting up a secure downloads area for Digging into WordPress. And when I finally discovered a solution, I told myself that it was definitely something I had to share here at Perishable Press.
Apparently, there is much to be desired when it comes to sending proper HTTP headers for file downloads. Different browsers (and not just IE) require different headers, and will error if not present exactly the way they expected. Confounding that equation is the fact that different file types also require specific headers. Then there are issues with sending an accurate (or should I say “acceptable”?) Content-Length
headers when file compression is involved. Needless to say, finding a set of headers that works for all file types in all browsers is next to impossible. And I won’t even get into the issues involved with readfile()
and large-download file-sizes.
Download Headers that actually work
After trying hundreds of different headers and combinations, I hit upon a set that works great for ZIP downloads (and other file types as well) in all tested browsers. Here’s what they look like using PHP:
<?php // HTTP Headers for ZIP File Downloads
// https://perishablepress.com/press/2010/11/17/http-headers-file-downloads/
// set example variables
$filename = "Inferno.zip";
$filepath = "/var/www/domain/httpdocs/download/path/";
// http headers for zip downloads
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/octet-stream");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filepath.$filename));
ob_end_flush();
@readfile($filepath.$filename);
?>
This PHP script is known to work under the following conditions:
- Operating System: Linux
- Server: Apache/2.2.3 (CentOS)
- MYSQL Version: 5.0.77-log
- PHP Version: 5.2.6
- PHP Safe Mode: Off
- PHP Allow URL fopen: On
- PHP Memory Limit: 256M
- PHP Max Upload Size: 2M
- PHP Max Post Size: 8M
- PHP Max Script Execute Time: 30s
With this code, the downloads work in the following tested browsers:
- Firefox 3.0, 3.5 (Mac & PC)
- Opera 8, 9, 10 (Mac & PC)
- Internet Explorer 7, 8
- Chrome 7.0.517
- Camino 2
- Safari 5 (PC)
- Safari 3 (Mac)
The downloads work for the following types of files (including small and large file types):
.zip
.txt
.pdf
.jpg
Obviously, I didn’t test every file type in every browser, but the positive results from those listed here suggest a much wider range of files and browsers that will work. For the file sizes, I tested small files only a few bytes in length, and also large files up to around 20MB or so. Also would like to give a shout to the Live HTTP Headers extension for Firefox. It proved indispensable throughout the troubleshooting/testing/pulling-my-hair-out process.
As always, if you can contribute to the content of this post with further information about sending proper HTTP Headers for file downloads, you may just save a life ;)
25 responses to “HTTP Headers for ZIP File Downloads”
if i may ask
what should we code for download the zip of the directory
the zip file is not exist, it is generated using PHP and containing all files of specified folder
is it possible?
Thanks
I am not sure how this code is best integrated into WordPress … I can see how to use it in a normal php context, but WordPress has it’s complex get_header() getting in the way.
Would it be possible to post an example of how to get this working with WordPress?
Thank you.
I had been getting corrupt zip files, and was searching everywhere for a fix, and these three lines just saved me.
while (ob_get_level()) {
ob_end_clean();
}
Thanks Vladimir!
can you give as the code i have the same problem
I saw smartReadFile (Reads the requested portion of a file and sends its contents to the client with the appropriate headers.)
it started here
http://php.net/manual/en/function.readfile.php#86244
and was updated at the end of
https://groups.google.com/forum/#!msg/jplayer/nSM2UmnSKKA/Hu76jDZS4xcJ
Thanks for this. Scouring the web looking for a solution described me perfectly.
I was getting odd characters – looked like a hex number – before any zip files that I was sending through a script. They’d download okay in Chrome, but when I tried to get it to download via fsockopen the file was invalid.
But it’s working now, and I thank you for that.
I am generating zipfile dynamically, in that case, how can I set filesize header?
Sourabh Bajaj: You issue a SOAP request to
http://god.org
calling thePredictFileSizeOfMyZippedFilesPlease()
method and use the response in the content-length header.…or you send the content-length header when the zipfile is completed and you actually *know* the filesize…
That worked for me! ur awesome and wonderful for sharing this!!, may u have a wonderful day
thank you
hello,
I found to zip file related to link in php. & it’s very useful link:-
http://www.phphunt.com/131/zip-file-in-php
i want to change the zip file name during download. please get me idea
Thank you for that. It works for me fine.