0
votes

I need to extract the contents of a directory within a zip archive in to an output directory.

The directory name inside the zip could be anything. However it will be the only directory in the base of the zip archive. There could be any number of files in the directory, in the zip archive, though.

The file structure inside the zip would be along theses lines:

- d0001
  - My Folder
    - view.php
    - tasks.txt
  - file1.txt
  - picture1.png
  - document.doc

The contents of the output directory needs to look like this:

- My Folder
  - view.php
  - tasks.txt
- file1.txt
- picture1.png
- document.doc

The code I currently have deletes the contents of the output directory and extracts the entire zip archive in to the directory:

function Unzip($source, $destination) {
    $zip = new ZipArchive;
    $res = $zip->open($source);
    if($res === TRUE) {
      $zip->extractTo($destination);
      $zip->close();
      return true;
    } else {
      return false;
    }
}
function rrmdir($dir, $removebase = true) {
    if(is_dir($dir)) {
        $objects = scandir($dir);
        foreach($objects as $object) {
            if($object != "." && $object != "..") {
                if(filetype($dir."/".$object) == "dir") rrmdir($dir."/".$object); else unlink($dir."/".$object);
            }
        }
        reset($objects);
        if($removebase == true)
          rmdir($dir);
    }
}

$filename = '/home/files.zip';
$dest = '/home/myfiles/';

if(is_dir($dest)) {
  rrmdir($dest, false);

  $unzip = Unzip($filename, $dest);
  if($unzip === true) {
    echo 'Success';
  } else
    echo 'Extraction of zip failed.';
} else
  echo 'The output directory does not exist!';

All the function rrmdir() does is remove the contents of the output directory.

1

1 Answers

0
votes

I managed to get it to work by working with file streams manually instead of using extractTo().

The script extracts all the files in the base of the archive and all the files in directories in the base of the archive in to the output folder.

For example, if this is the archives contents:

- d0001
  - My Folder
    - view.php
    - tasks.txt
  - file1.txt
  - picture1.png
  - document.doc
- d2
  - another1.png
  - pic2.gif
- doc1.txt
- mylist.txt

The contents of the output directory will look like this:

- My Folder
  - view.php
  - tasks.txt
- file1.txt
- picture1.png
- document.doc
- another1.png
- pic.gif
- doc1.txt
- mylist.txt

The code:

function rrmdir($dir, $removebase = true) {
    if(is_dir($dir)) {
        $objects = scandir($dir);
        foreach($objects as $object) {
            if($object != "." && $object != "..") {
                if(filetype($dir."/".$object) == "dir") rrmdir($dir."/".$object); else unlink($dir."/".$object);
            }
        }
        reset($objects);
        if($removebase == true)
          rmdir($dir);
    }
}

$filename = '/home/files.zip';
$dest = '/home/myfiles/';

if(is_dir($dest)) {
  // Remove directory's contents
  rrmdir($dest, false);

  // Load up the zip
  $zip = new ZipArchive;
  $unzip = $zip->open($filename);
  if($unzip === true) {
    for($i=0; $i<$zip->numFiles; $i++) {
      $name = $zip->getNameIndex($i);

      // Remove the first directory in the string if necessary
      $parts = explode('/', $name);
      if(count($parts) > 1) {
        array_shift($parts);
      }
      $file = $dest . '/' . implode('/', $parts);

      // Create the directories if necessary
      $dir = dirname($file);
      if(!is_dir($dir))
        mkdir($dir, 0777, true);

      // Check if $name is a file or directory
      if(substr($file, -1) == "/") {
        // $name is a directory
        // Create the directory
        if(!is_dir($file))
          mkdir($file, 0777, true);
      } else {
        // $name is a file
        // Read from Zip and write to disk
        $fpr = $zip->getStream($name);
        $fpw = fopen($file, 'w');
        while($data = fread($fpr, 1024)) {
          fwrite($fpw, $data);
        }
        fclose($fpr);
        fclose($fpw);
      }
    }
    echo 'Success';
  } else
    echo 'Extraction of zip failed.';
} else
  echo 'The output directory does not exist!';