Question

    if ($zip->open($zipFile, ZipArchive::CREATE) !== TRUE) {
        (...)
    } else {
        $zip->addFile($tempDir.$fileName.".xls", $fileName.".xls");
        // The array contains the directory structure of the files to add
        foreach ($list_attachments as $dir_name => $attachment_files) {
            if (!empty($attachment_files)) {
                $zip->addEmptyDir($dir_name);
                foreach ($attachment_files as $attachment) {
                    $zip->addFile($tempDir.$dir_name."/".$attachment, $dir_name."/".$attachment));
                    unlink($tempDir.$dir_name."/".$attachment);
                }
                rmdir($tempDir.$dir_name."/");
            }
        }
        $zip->close();
    }

Please don't mind potential typos in the variable names, I rewrote them and the comment in English to make them more readable. If I run the code as is, it will delete the files and the directories but won't create the archive. I ran checks on return values and addEmptyDir, addFile, unlink and rmdir all work fine. However, it seems that removing the files prevents the archive from closing properly, and thus the file isn't created.

I circumvented it by moving the unlink and rmdir calls after the $zip->close(), so the files are only deleted after the archive is created. However, is forces me to have twice the loops, and from what I've gathered looking at the documentation and zip-related questions here there shouldn't be any issue with unlinking like I did. Does anyone know for which reason this could happen?

Was it helpful?

Solution

The zip will be finally written to file AFTER you've called $zip->close(). Until this point everything happens in memory, no 'zipping' is done. That's why you can delete the unzipped files only after you've called $zip->close() successfully.

The documentation even says the following:

When a file is set to be added to the archive, PHP will attempt to lock the file and it is only released once the ZIP operation is done. In short, it means you can first delete an added file after the archive is closed.

However, the locks will not prevent you from deleting the files anyway, they are just "hints", the big problem is that the files need to be there for processing on close().


So the inner loop should look like this:

foreach ($attachment_files as $attachment) {
    $zip->addFile($tempDir.$dir_name."/".$attachment, $dir_name."/".$attachment));
    $to_be_unlinked []= $tempDir.$dir_name."/".$attachment;
}

Later on, unlink the files:

...
foreach($to_be_unlinked as $file) {
    unlink($file);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top