There are similar questions about creating and downloading zip files in PHP and I can do that. The problem is that some zip files are bigger (> 200 MB) and PHP does not wait until the zip file is complete before is starts downloading.
The speed of compressing is OK. I tried storing the files uncompressed is only marginally faster and is not solving the problem.
The function for creating the zip file looks like this:
function makeRouteArchive($routeID) {
// Get real path for our folder
$rootPath = self::get_location($routeID);
$relRootPath = $rootPath;
while (!scandir($relRootPath)) {
$relRootPath = '../'.$relRootPath;
}
$info = new SplFileInfo($relRootPath);
$rootlen = strlen( $info->getRealPath());
$zippath = $this->archive_root;
while (!scandir($zippath)){
$zippath = '../'.$zippath;
}
$routeText = 'oute'.sprintf('%07d',$routeID);
$zipfilename = 'route'.sprintf('%07d',$routeID).'.zip';
$zipfile = $zippath.$zipfilename;
// Initialize archive object
$zip = new ZipArchive();
// Create recursive directory iterator
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($relRootPath), RecursiveIteratorIterator::SELF_FIRST );
$zip->open($zipfile, ZipArchive::CREATE | ZipArchive::OVERWRITE);
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, $rootlen + 1);
if (!strpos($relativePath,$routeText) === false) {
if (strpos($relativePath,'Picture_') > 0) {
$relativePath = str_replace('Picture_','Pictures/',$relativePath);
$relativePath = 'Storage Card/RoutAbel/'.$relativePath;
} elseif (strpos($relativePath,'Media_') > 0) {
$relativePath = str_replace('Media_','Media/',$relativePath);
$relativePath = 'Storage Card/RoutAbel/'.$relativePath;
} elseif (strpos($relativePath,'ARobjects_') > 0) {
$relativePath = str_replace('ARobjects_','ARobjects/',$relativePath);
$relativePath = 'Storage Card/RoutAbel/'.$relativePath;
} elseif (strpos($relativePath,'_') == 12 ) {
$relativePath = 'Storage Card/RoutAbel/'.substr_replace($relativePath,'/Content/',12,1);
$relativePath = str_replace('_Marker','/Content/Marker', $relativePath);
$relativePath = str_replace('_Slider','/Content/Slider', $relativePath);
}
// Add current file to archive
$zip->addFile($filePath, $relativePath);
}
}
}
// Zip archive will be created only after closing object
$zip->close();
return $result;
}
The main code is simply :
$zipfile = makeRouteArchive($routeID);
if (headers_sent()) {
echo 'HTTP header already sent';
} else {
if (!is_file($zipfile)) {
header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
echo 'File not found';
} else if (!is_readable($zipfile)) {
header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
echo 'File not readable';
} else {
while (ob_get_level()) {
ob_end_clean();
}
ob_start();
header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: Binary");
header("Content-Length: ".filesize($file));
header('Pragma: no-cache');
header("Content-Disposition: attachment; filename=\"".basename($zipfile)."\"");
ob_flush();
ob_clean();
readfile($zipfile);
exit;
}
}
The code is working perfect, as long as there are not to many or to large files to be zipped.
My problem: How can I force the function to wait until the zip file is ready?