PHP压缩下载文件夹脚本生成0字节文件问题求助
PHP压缩大量文件后下载得到0字节Zip文件的问题
我写了一个PHP脚本用来压缩指定文件夹并提供下载,但当文件夹包含大量文件时,下载的zip文件大小为0字节。我已经用file_exists验证过文件路径是有效的,请问问题出在哪里?
原脚本代码:
<?php // 定义要压缩的文件夹路径 $folder_path = '/CA11.2.4/logs/'; // 定义带时间戳的压缩文件名 $zip_file_name = 'logs_' . date('Ymd_His') . '.zip'; // 初始化ZipArchive实例 $zip = new ZipArchive(); // 打开压缩文件准备写入 if ($zip->open($zip_file_name, ZipArchive::CREATE) !== TRUE) { die ('无法创建压缩包'); } // 将文件夹中的文件添加到压缩包 $dir = opendir($folder_path); while ($file = readdir($dir)) { if (is_file($folder_path . $file)) { $zip->addFile($folder_path . $file, $file); } } // 关闭目录句柄 closedir($dir); // 关闭压缩文件 $zip->close(); // 设置下载响应头 header('Content-Type: application/zip'); header('Content-Disposition: attachment; filename="' . $zip_file_name . '"'); header('Content-Length: ' . filesize($zip_file_name)); // 输出压缩文件给客户端 readfile($zip_file_name); // 删除服务器上的压缩文件(已注释) //unlink($zip_file_name); // 跳转回来源页面(已注释) //header('Location: ' . $_SERVER['HTTP_REFERER']); ?>
我最初怀疑路径未被识别,因此添加了以下代码片段验证,结果显示路径有效:
<?php $path = '/path/to/folder/file.txt'; if (file_exists($path)) { echo '路径在服务器上存在'; } else { echo '路径在服务器上不存在'; } ?>
问题分析与解决方案
核心问题排查
未捕获
addFile执行失败
当文件夹文件数量大时,可能存在部分文件无法读取(权限不足、文件被占用、特殊字符文件名),但脚本没有检查addFile的返回值,一旦某个文件添加失败,后续流程可能异常中断,导致Zip文件未正常写入。未处理子目录
原脚本仅处理文件夹下的直接文件,若目标目录包含子文件夹,子目录内的文件不会被添加。如果根目录无文件,就会生成空Zip。内存/执行时间限制
压缩大量文件时,PHP可能因内存不足或执行超时,导致Zip文件未完成写入就终止,最终生成空文件。文件大小缓存问题
$zip->close()后系统可能还在刷新磁盘缓冲,此时调用filesize获取的大小可能不准确,甚至为0。
针对性解决方法
添加
addFile错误检查
修改循环逻辑,每次添加文件都验证结果,同时跳过.和..目录:while ($file = readdir($dir)) { if ($file === '.' || $file === '..') continue; $full_path = $folder_path . $file; if (is_file($full_path)) { if (!$zip->addFile($full_path, $file)) { error_log("添加文件失败: $full_path"); // 可选择终止或继续,根据需求调整 // die("添加文件失败: $full_path"); } } }递归遍历子目录
编写递归函数处理所有层级的文件和目录:function addFolderToZip($folder, $zip, $parent_path = '') { $dir = opendir($folder); while ($file = readdir($dir)) { if ($file === '.' || $file === '..') continue; $full_path = $folder . '/' . $file; $relative_path = $parent_path . $file; if (is_file($full_path)) { $zip->addFile($full_path, $relative_path); } elseif (is_dir($full_path)) { $zip->addEmptyDir($relative_path); addFolderToZip($full_path, $zip, $relative_path . '/'); } } closedir($dir); } // 替换原有的文件添加代码 addFolderToZip($folder_path, $zip);调整PHP运行参数
在脚本开头增加内存和执行时间限制:ini_set('memory_limit', '256M'); // 根据实际文件大小调整 set_time_limit(300); // 设置为5分钟,避免超时中断刷新文件状态缓存
在$zip->close()后刷新文件状态,确保获取正确的文件大小:$zip->close(); clearstatcache(true, $zip_file_name); // 刷新指定文件的状态缓存检查权限设置
确保PHP进程对/CA11.2.4/logs/下的所有文件有读取权限,同时对脚本所在目录有写入权限(用于生成Zip文件)。
内容的提问来源于stack exchange,提问作者Ramneek Singh
相关产品推荐
相关产品推荐

