Search code examples
phpreadfilephp-ziparchive

PHP readfile download timing out


My PHP script keeps crashing/timing out, presumably because of the readfile. My goal is to generate the zip, let the user download it, and remove the zip afterwards.

Code:

<?php

if(isset($_POST['version']) && isset($_POST['items']) && isset($_POST['identifier'])) {

$identifier = $_POST['identifier'];
$version = $_POST['version'];
$tmp = dirname(__FILE__) . "/download/";
$zipfile = $tmp . $identifier . ".zip";
$name = "Program v" . $version . ".zip";
$path = dirname(__FILE__) . "\\download\\template\\" . $version;

$files = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($path),
    RecursiveIteratorIterator::LEAVES_ONLY
);

$zip = new ZipArchive();

if ($zip->open($zipfile, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) {

    foreach ($files as $name => $file) {
        // Skip directories (they would be added automatically)
        if (!$file->isDir()) {
            // Get real and relative path for current file
            $filePath = $file->getRealPath();
            $relativePath = substr($filePath, strlen($path) + 1);

            //echo "adding " . $file . " as " . $relativePath;
            // Add current file to archive
            $zip->addFile($file, $relativePath);
        }
    }

    $zip->close();
} else {
    die('Error: Unable to create zip file');
}

// Stream the file to the client
header('Content-Type: application/zip');
header('Content-Length: ' . filesize($zipfile));
header('Content-disposition: attachment; filename="'.$name.'"');
readfile($zipfile);
exit;

}

Everything works up until the download part. The zip file gets generated fine on the server, when trying to download it, it crashes.

Sometimes it shows an error in my logs, which is telling me it expects a valid path and that an object is given. Even though it strictly puts out a string (the path).

Note: The file is less than 300 KiB so I highly doubt the webserver is running out of memory.

I'm pretty lost, any help is highly appreciated.


Solution

  • The problem is with the generation of the ZIP file. The addFile method requires a file path as its first parameter, not an object. See documentation:

    bool ZipArchive::addFile ( string $filename [, string $localname = NULL [, int $start = 0 [, int $length = 0 ]]] )

    http://php.net/manual/en/ziparchive.addfile.php

    Therefore in your case the correct expression would be:

    $zip->addFile($filePath, $relativePath);