Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ZipArchive issue "Error 21 - Is a Directory" in PHP

I'm generating a set of HTML, CSS, and image files and I'm using ZipArchive to compress them into a zip file. I've confirmed that the generated assets are valid, but when I attempt to zip the set of files, the resulting archive file is not able to be opened.

I'm not getting any errors in the PHP and when I echo $zip->close() it returns true which I assume to mean that it was able to write to and save the file without issue. Opening the zip with the mac Archive Utility throws this error:

"Unable to expand "filename.zip" into "Downloads". (Error 21 - Is a directory.)

What might be wrong here?

Here is the entire PHP script:

<?php
$ref = $_SERVER["HTTP_REFERER"];
$html = $_REQUEST['html'];
$images = $_REQUEST['images'];

$folder = uniqid();
$prepped = str_replace($ref.'server/php/files/', 'images/', $html);

mkdir("./runways/$folder", 0777);
mkdir("./runways/$folder/images", 0777);
mkdir("./runways/$folder/css", 0777);


file_put_contents('./runways/'.$folder.'/index.html',$prepped);
copy('../../css/runway.css', './runways/'.$folder.'/css/runway.css');

foreach($images as $image) {
    $i = urldecode(str_replace($ref.'server/php/files/', '', $image));
    $idata = file_get_contents('./files/'.$i);
    file_put_contents('./runways/'.$folder.'/images/'.$i, $idata);

}

//echo $ref.'server/php/runways/'.$folder.'/';

$sourcefolder = './runways/'.$folder.'/';
$zipfilename = $folder.'.zip';

$dirlist = new RecursiveDirectoryIterator($sourcefolder);
$filelist = new RecursiveIteratorIterator($dirlist);

ini_set('max_execution_time', 5000);
$zip = new ZipArchive();

if ($zip->open('./zips/'.$zipfilename, ZIPARCHIVE::CREATE) !== TRUE) {
    die ("Could not open archive");
}

foreach ($filelist as $key=>$value) {
    $zip->addFile(realpath($key), $key) or die ("ERROR: Could not add file: $key");
}
$zip->close();

echo $ref.'server/php/zips/'.$zipfilename;

?>
like image 942
user3658604 Avatar asked May 20 '14 22:05

user3658604


2 Answers

A little background: I have chosen for my website to be wiped, and I have downloaded public_html as a zip file. I was a bit scared I wouldn't be able restore my website once it has been reset.

A quick solution (and the one that worked for me) is to use an app from the App Store called The Unarchiver. I had this same issue when using a file compressed from the cPanel file manager, and The Unarchiver seemed to fix it.

like image 91
LoganDark Avatar answered Oct 24 '22 03:10

LoganDark


The archive you're creating includes current working directories and parent directories (filenames "." and ".."), which you should leave out. For example if you view the contents of an archive the original code creates, you'll see something like this:

$ unzip -l 54b69fbd2de29.zip 
Archive:  54b69fbd2de29.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  01-14-15 09:56   ./runways/54b69fbd2de29/.
        0  01-14-15 09:56   ./runways/54b69fbd2de29/..
        0  01-14-15 09:56   ./runways/54b69fbd2de29/css/.
        0  01-14-15 09:56   ./runways/54b69fbd2de29/css/..
       12  01-14-15 09:56   ./runways/54b69fbd2de29/css/runway.css
        0  01-14-15 09:56   ./runways/54b69fbd2de29/images/.
        0  01-14-15 09:56   ./runways/54b69fbd2de29/images/..
       26  01-14-15 09:56   ./runways/54b69fbd2de29/images/image1.jpg
       31  01-14-15 09:56   ./runways/54b69fbd2de29/images/image2.jpg
        6  01-14-15 09:56   ./runways/54b69fbd2de29/index.html
 --------                   -------
       75                   10 files

You don't want "./runways/54b69fbd2de29/." or "./runways/54b69fbd2de29/..", etc. Here's one way to fix this, change the final foreach to the following (note also that you don't need $key=>$value, just $key):

foreach ($filelist as $key) {
    if (!preg_match('/\/\.{1,2}$/',$key)){
        $zip->addFile(realpath($key), $key) or die ("ERROR: Could not add file: $key");
    }
}

The resulting archive is valid, and looks like this:

unzip -l 54b6a39d55a63.zip 
Archive:  54b6a39d55a63.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
       12  01-14-15 10:13   ./runways/54b6a39d55a63/css/runway.css
       26  01-14-15 10:13   ./runways/54b6a39d55a63/images/image1.jpg
       31  01-14-15 10:13   ./runways/54b6a39d55a63/images/image2.jpg
        6  01-14-15 10:13   ./runways/54b6a39d55a63/index.html
 --------                   -------
       75                   4 files
like image 41
jaybrau Avatar answered Oct 24 '22 05:10

jaybrau