35

Well, first of all, this is my folder structure:

images/

image1.png
image11.png
image111.png
image223.png
generate_zip.php

And this is mine generate_zip.php:

<?php

    $files = array($listfiles);

    $zipname = 'adcs.zip';
    $zip = new ZipArchive;
    $zip->open($zipname, ZipArchive::CREATE);
    foreach ($files as $file) {
      $zip->addFile($file);
    }
    $zip->close();

    header('Content-Type: application/zip');
    header("Content-Disposition: attachment; filename='adcs.zip'");
    header('Content-Length: ' . filesize($zipname));
    header("Location: adcs.zip");

    ?>

How to gather all the files from "images/" folder, except "generate_zip.php", and make it a downloadable .zip? In this case the "images/" folder always have a different image. Is that possible?

T.Todua
  • 53,146
  • 19
  • 236
  • 237
Ygor Montenegro
  • 659
  • 1
  • 12
  • 26

6 Answers6

69

======= Working solution !======

includes all sub-folders:

new GoodZipArchive('path/to/input/folder',    'path/to/output_zip_file.zip') ;

at first, include this piece of code.

T.Todua
  • 53,146
  • 19
  • 236
  • 237
  • 3
    If it's the best solution , i don't know, but i +1'ed it cause this worked for me aswell – Jakob Sternberg Mar 18 '14 at 23:11
  • This is a good answer, but it's not based on the question that OP asked, in which he specified that he only cared about the single directories image files. Just thought that should be clarified as anyone who is trying to do exactly what OP asked would find this code does not do exactly that. – skrilled Oct 20 '14 at 23:51
  • Thanks! Just curious, how can we include multiple folders? – NiCk Newman Nov 15 '15 at 23:22
  • 1
    I´m calling this file with a service from angular. The file isn´t get downloaded. Any suggestions? – m1crdy Mar 11 '16 at 15:58
  • This works, Although how do I allow the user to save it elsewhere by opening the save dialog window, instead of saving it in the same place the original folder is. –  May 17 '17 at 13:22
  • Is there a way to have this exclude certain files and directories? – drooh Aug 02 '18 at 00:22
  • @Ngob Change row 14: `if($input_folder && $output_zip_file) ` in `if($input_folder !== false && $output_zip_file !== false)` to manage '0' named folders. – Michele DC May 28 '19 at 14:51
  • 1
    @Ngob fixed now – T.Todua May 28 '19 at 14:58
31

this will ensure a file with .php extension will not be added:

   foreach ($files as $file) {
        if(!strstr($file,'.php')) $zip->addFile($file);
    }

edit: here's the full code rewritten:

<?php

    $zipname = 'adcs.zip';
    $zip = new ZipArchive;
    $zip->open($zipname, ZipArchive::CREATE);
    if ($handle = opendir('.')) {
      while (false !== ($entry = readdir($handle))) {
        if ($entry != "." && $entry != ".." && !strstr($entry,'.php')) {
            $zip->addFile($entry);
        }
      }
      closedir($handle);
    }

    $zip->close();

    header('Content-Type: application/zip');
    header("Content-Disposition: attachment; filename='adcs.zip'");
    header('Content-Length: ' . filesize($zipname));
    header("Location: adcs.zip");

    ?>
skrilled
  • 5,350
  • 2
  • 26
  • 48
  • ok, but how to list all the files from the images/ directory? inside array? – Ygor Montenegro Jul 17 '13 at 19:31
  • http://php.net/manual/en/function.readdir.php has what you need in that regards, example #2 is probably easiest. you could extend if ($entry != "." && $entry != "..") to if ($entry != "." && $entry != ".." && !strstr($entry,'.php')) and do the zip add in that loop too instead of my above example. – skrilled Jul 17 '13 at 19:33
  • Already tried, but how to put the while result inside the array();? – Ygor Montenegro Jul 17 '13 at 19:34
  • change $files = array($listfiles); to $files = array(); then in the while loop do array_push($listfiles,$entry); – skrilled Jul 17 '13 at 19:35
  • edited my answer with your code as how i would expect you wanted it :) – skrilled Jul 17 '13 at 19:41
  • 1
    like this: `if ($handle = opendir('../adc/')) { while (false !== ($entry = readdir($handle))) { if ($entry != "." && $entry != "..") { array_push($listfiles, "'$entry, "); } } closedir($handle); } $files = array();` Still not generating.. – Ygor Montenegro Jul 17 '13 at 19:42
  • Its working only for files in the selected folder but how can we add all subfolders in the zip file..?? – Ritesh Oct 20 '14 at 10:22
  • @Ritesh see answer below. My answer was specific to OP whereas his answer is generic to other case scenarios. – skrilled Oct 20 '14 at 23:52
1

Since you just need specific files from a directory to create ZipArchive you can use glob() function to do this.

<?php
    $zip = new ZipArchive;
    $download = 'download.zip';
    $zip->open($download, ZipArchive::CREATE);
    foreach (glob("images/*.png") as $file) { /* Add appropriate path to read content of zip */
        $zip->addFile($file);
    }
    $zip->close();
    header('Content-Type: application/zip');
    header("Content-Disposition: attachment; filename = $download");
    header('Content-Length: ' . filesize($download));
    header("Location: $download");
 ?>

Don't use glob() if you try to list files in a directory where very much files are stored (more than 100.000). You get an "Allowed memory size of XYZ bytes exhausted ..." error.

readdir() is more stable way.

way2vin
  • 2,411
  • 1
  • 20
  • 15
1

I went with way2vin's solution. However I had to replace

$zip->addFile("{$file}");

with

$zip->addFromString(basename($file), file_get_contents($file));

which did the trick. Found this here: Creating .zip file

Marchand
  • 11
  • 2
0

change your foreach loop to this to except generate_zip.php

 foreach ($files as $file) {
     if($file != "generate_zip.php"){
        $zip->addFile($file);
     }
 }
shyammakwana.me
  • 5,562
  • 2
  • 29
  • 50
0
<?php 
ob_start();
$zip = new ZipArchive; 
$zip->open('sample.zip',  ZipArchive::CREATE);
$srcDir = "C:\\xampp\\htdocs\\uploads"; //location of the directory
$files= scandir($srcDir);
print_r($files);  // to check if files are actually coming in the array

unset($files[0],$files[1]);
foreach ($files as $file) {
    $zip->addFile($srcDir.'\\'.$file, $file);
    echo "bhandari";
}
$zip->close();

$file='sample.zip';
if (headers_sent()) {
    echo 'HTTP header already sent';
} else {
    if (!is_file($file)) {
        header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
        echo 'File not found';
    } else if (!is_readable($file)) {
        header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
        echo 'File not readable';
    } else {
        header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
        header("Content-Type: application/zip");
        header("Content-Transfer-Encoding: Binary");
        header("Content-Length: ".filesize($file));
        header("Content-Disposition: attachment; filename=\"".basename($file)."\"");
        while (ob_get_level()) {
            ob_end_clean();
          }
        readfile($file);
        exit;
    }
}



?>`enter code here`

Note: Don't forget to use ob_start(); and end .

crenshaw-dev
  • 7,504
  • 3
  • 45
  • 81
sawan
  • 3
  • 2