在PHP中创建大的zipfile并在zipfile完成后下载

ix0qys7i  于 2023-03-07  发布在  PHP
关注(0)|答案(1)|浏览(151)

在PHP中创建和下载zip文件也有类似的问题,我可以做到这一点。问题是有些zip文件更大(〉200 MB),PHP不会等到zip文件完成后才开始下载。
压缩的速度还可以。我试过存储未压缩的文件,只是稍微快一点,并没有解决问题。
创建zip文件的函数如下所示:

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;
}

主要代码如下:

$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;
        }
    }

代码是完美的工作,只要没有太多或太大的文件要压缩。

**我的问题:**如何强制函数等待zip文件准备好?

yhqotfr8

yhqotfr81#

ob_start()会导致例程清除缓冲区,从而使例程无法完成zip文件的创建

相关问题