Dynamically created zip files by ZipStream in PHP won't open in OSX

The problem was in the "version needed to extract" field, which I found by doing a hex diff on a file created by ZipStream vs a file created by Info-zip and going through the differences, trying to resolve them.

ZipStream by default sets it to 0x0603. Info-zip sets it to 0x000A. Zip files with the former value don't seem to open in Archive Utility. Perhaps it doesn't support the features at that version?

Forcing the "version needed to extract" to 0x000A made the generated files open as well in Archive Utility as they do everywhere else.

Edit: Another cause of this issue is if the zip file was downloaded using Safari (user agent version >= 537) and you under-reported the file size when you sent out your Content-Length header.

The solution we employ is to detect Safari >= 537 server side and if that's what you're using, we determine the difference between the Content-Length size and the actual size (how you do this depends on your specific application) and after calling $zipStream->finish(), we echo chr(0) to reach the correct length. The resulting file is technically malformed and any comment you put in the zip won't be displayed, but all zip programs will be able to open it and extract the files.

IE requires the same hack if you're misreporting your Content-Length but instead of downloading a file that doesn't work, it just won't finish downloading and throws a "download interrupted".


use ob_clean(); and flush();

Example :

    $file =  __UPLOAD_PATH . $projectname . '/' . $fileName;

    $zipname = "watherver.zip"
    $zip = new ZipArchive(); 
    $zip_full_path_name = __UPLOAD_PATH . $projectname . '/' . $zipname;
    $zip->open($zip_full_path_name, ZIPARCHIVE::CREATE);
    $zip->addFile($file); // Adding one file for testing
    $zip->close();

    if(file_exists($zip_full_path_name)){
        header('Content-type: application/zip');
        header('Content-Disposition: attachment; filename="'.$zipname.'"');
        ob_clean();
        flush();
        readfile($zip_full_path_name);
        unlink($zip_full_path_name);
    }

I've had this exact issue but with a different cause.

In my case the php generated zip would open from the command line, but not via finder in OSX.

I had made the mistake of allowing some HTML content into the output buffer prior to creating the zip file and sending that back as the response.

<some html></....>
<?php

// Output a zip file...

The command line unzip program was evidently tolerant of this but the Mac unarchive function was not.

Tags:

Php

Macos

Zip