Search code examples
phpfiledownloadzip

PHP Zip file download error when opening


I need to download a zip file from a website as I am going to require to coalesce multiple files in a single download (up to 100 individual files-ish).

When attempting to create the zip file, it downloads as intended, the file name appears in the format "YYYY.MM.DD - HH.MM.SS" also as intended. My issue occurs when attempting to open the zip file in windows 7 (or winzip) - I get the error message below. This happens repeatedly from multiple attempts.

I assume that I have made an error while coding the creation or download of the zip file, rather than the zip file format itself being an issue as I can open different zip files - can anyone see the mistake I have probably made? (code included below error image)

I have attempted to use Download multiple files as a zip-file using php as a reference.

//backup file name based on current date and time
$filename = date("Y.m.j - H.i.s");
//name of zip file used when downloading
$zipname = 'temp.zip';
//create new zip file
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
//yes, I know the zip file is empty currently - I've cut the code from here for
//now as the zip file doesn't function with / without it currently
$zip->close();

//download file from temporary file on server as '$filename.zip'
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$filename.'.zip');
header('Content-Length: ' . filesize($zipname));
readfile($zipname);

Solution

  • Check that the web server user has write permission to the folder where you're creating the ZIP file. Notwithstanding the documentation, ZipArchive::open() will fail silently and return true (i.e. success) if it cannot create the ZIP file. Further, ZipArchive::addFile() will seemingly add as many files as you wish to this non-existent archive, also without reporting an error. The first point at which an error appears is when ZipArchive::close() returns `false'. No error messages appear in the error logs, either.

    Readfile() will report an error to the logs and fail, so the result is a zero-length ZIP file on your local hard disk.

    The reason seems to be that the ZipArchive class is only assembling a list of files in memory until it's closed, at which point it assembles all the files into the Zip file. If this can't be done then ZipArchive::close() returns false.

    Note: if the zip file is empty, it might not be created at all! Your download will proceed, but readfile() will fail and you'll get a zero-length ZIP file downloaded.

    What to do?

    Add a little error checking to your code to report some of this:

    $zip = new ZipArchive;
    $zip->open($zipname, ZipArchive::CREATE);
    
    // Add your files here
    
    if ($zip->close() === false) {
       exit("Error creating ZIP file");
    };
    
    
    //download file from temporary file on server as '$filename.zip'
    if (file_exists($zipname)) {
    
        header('Content-Type: application/zip');
        header('Content-disposition: attachment; filename='.$filename.'.zip');
        header('Content-Length: ' . filesize($zipname));
        readfile($zipname);
    } else {
        exit("Could not find Zip file to download");
    }