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;
?>
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