131

How can I download multiple files as a zip-file using php?

Zoe
  • 27,060
  • 21
  • 118
  • 148
  • You can use the xip.lib.php Class lib. [zip.lib.php](http://www.phpclasses.org/browse/file/3631.html) For examples, refer to this [article](https://web.archive.org/web/20100715193617/http://www.weberdev.com/get_example-4066.html) – Abdel Raoof Olakara Nov 18 '09 at 08:40

4 Answers4

250

You can use the ZipArchive class to create a ZIP file and stream it to the client. Something like:

$files = array('readme.txt', 'test.html', 'image.gif');
$zipname = 'file.zip';
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
foreach ($files as $file) {
  $zip->addFile($file);
}
$zip->close();

and to stream it:

header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$zipname);
header('Content-Length: ' . filesize($zipname));
readfile($zipname);

The second line forces the browser to present a download box to the user and prompts the name filename.zip. The third line is optional but certain (mainly older) browsers have issues in certain cases without the content size being specified.

Community
  • 1
  • 1
cletus
  • 616,129
  • 168
  • 910
  • 942
  • 4
    Shouldn't it be `$zip = new ZipArchive;` instead of `$zip = new ZipFile;` ? – Matthieu Jan 25 '12 at 20:32
  • @Matthieu The parentheses are not necessary. Look in examples: http://www.php.net/manual/en/ziparchive.open.php – Lars Gyrup Brink Nielsen Feb 20 '13 at 22:40
  • 1
    What is the variable $zipfilename supposed to mean? – Pascal Klein Feb 12 '14 at 22:59
  • $zipfilename should read $zipname - it's the filename of the created zip as a string. – Chris Mar 31 '14 at 15:56
  • 1
    Its not working in windows default zip opener however working in win zipper or 7-zip. I'm trying to add image in zip folder and then download as zip – RN Kushwaha Feb 24 '15 at 13:13
  • Above header is not working in windows native zip opener. It says invalid zip, however perfect in ubuntu. – RN Kushwaha Feb 25 '15 at 05:51
  • this answer is not too good because people often zip archives that are not in the same directory as running script. use `readfile($zippath)` and `filesize($zippath)` instead of "zipname' – user151496 Feb 12 '16 at 16:34
  • While this works, I have the CPU maxing out at 100% during addFile() process. – Paranoid Android Jul 24 '17 at 11:43
  • 1
    I tried this but when I tried to unzip the zip-file it says that the archieve is not readable and the archieve may not be valid or its table of content could be encrypted. What's wrong? – Marianne Sjöberg May 15 '20 at 10:58
  • Using this example, my archive file is 0 bytes. But changing one line, as shown in the example by @SunLove, the archive works: change `$zip->addFile($file);` to `$zip->addFromString(basename($path), file_get_contents($path));` – Genki Nov 27 '20 at 06:51
  • 1
    I had to vary the name of the .zip file or else my browser repeatedly downloaded the exact same content, even though the list of files being archived by my script had changed. Seems like the file was cached. By including the `time()` in the filename, as shown in @SunLove's example, it worked. – Genki Nov 27 '20 at 07:36
  • adding files this way : $zip->addFromString(basename($file), file_get_contents($file)); works for me. – rahim.nagori Dec 18 '20 at 05:44
  • Use `$zip->addFile($file,basename($file));` if you want to remove the paths. https://stackoverflow.com/questions/3993105/php-creating-zips-without-path-to-files-inside-the-zip – tertek Jul 08 '21 at 12:34
47

This is a working example of making ZIPs in PHP:

$zip = new ZipArchive();
$zip_name = time().".zip"; // Zip name
$zip->open($zip_name,  ZipArchive::CREATE);
foreach ($files as $file) {
  echo $path = "uploadpdf/".$file;
  if(file_exists($path)){
  $zip->addFromString(basename($path),  file_get_contents($path));  
  }
  else{
   echo"file does not exist";
  }
}
$zip->close();
Ren
  • 1,111
  • 5
  • 15
  • 24
Sun Love
  • 744
  • 5
  • 9
1

Create a zip file, then download the file, by setting the header, read the zip contents and output the file.

http://www.php.net/manual/en/function.ziparchive-addfile.php

http://php.net/manual/en/function.header.php

Priyank Bolia
  • 14,077
  • 14
  • 61
  • 82
1

You are ready to do with php zip lib, and can use zend zip lib too,

<?PHP
// create object
$zip = new ZipArchive();   

// open archive 
if ($zip->open('app-0.09.zip') !== TRUE) {
    die ("Could not open archive");
}

// get number of files in archive
$numFiles = $zip->numFiles;

// iterate over file list
// print details of each file
for ($x=0; $x<$numFiles; $x++) {
    $file = $zip->statIndex($x);
    printf("%s (%d bytes)", $file['name'], $file['size']);
    print "
";    
}

// close archive
$zip->close();
?>

http://devzone.zend.com/985/dynamically-creating-compressed-zip-archives-with-php/

and there is also php pear lib for this http://www.php.net/manual/en/class.ziparchive.php

dev.meghraj
  • 8,542
  • 5
  • 38
  • 76