Deleting files after adding them to an archive prevents the archive's creation
Asked Answered
B

1

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

Ballance answered 3/2, 2014 at 13:2 Comment(0)
T
5

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);
}
Tobey answered 3/2, 2014 at 13:4 Comment(3)
So the code shown/given in other questions, for example link is wrong, since they unlink before closing themselves? I checked out a bit less than a dozen questions before asking, and all of them put their unlink inside the loop, so I figured my issue was something else.Ballance
Yes, seems so.. Funny that the answer you've linked got 16+ :)Tobey
This answer helped as I was deleting file before closing ZIP file. In my case it was generating error: 'Unknown: Cannot destroy the zip context:'Oxazine

© 2022 - 2024 — McMap. All rights reserved.