递归迭代器:包含zip中的目录和php文件


RecursiveIteratorIterator: include directory and php files in zip

我有一个脚本,其中zip目录,但需要添加*.php文件也。

添加../index.php时抛出错误。

下面脚本产生的错误是:

Fatal error: Uncaught exception 'UnexpectedValueException' with message 'RecursiveDirectoryIterator::__construct(../index.php): failed to open dir: Not a directory' in /home/mathtest/public_html/trig/admin/save.php:23 Stack trace: #0 /home/mathtest/public_html/trig/admin/save.php(23): RecursiveDirectoryIterator->__construct('../index.php') #1 {main} thrown in /home/mathtest/public_html/trig/admin/save.php on line 23

我的脚本:

<?php
/* CONFIG */
$pathToAssets = array("../images", "../Data", "../css", "../index.php");
$filename = "temp/backup.zip";
/* END CONFIG */

$zip = new ZipArchive();
$zip->open($filename, ZipArchive::CREATE);

//add folder structure
foreach ($pathToAssets as $thePath) {
    // Create recursive directory iterator
    $files = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($thePath), RecursiveIteratorIterator::LEAVES_ONLY
    );

    foreach ($files as $name => $file) {
        if ($file->getFilename() != '.' && $file->getFilename() != '..') {
            // Get real path for current file
            $filePath = $file->getRealPath();
            $temp = explode("/", $name);
            array_shift($temp);
            $newName = implode("/", $temp);
            // Add current file to archive
            $zip->addFile($filePath, $newName);
        }
    }
}
$zip->close();
$yourfile = $filename;
$file_name = basename($yourfile);
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: Binary");
header("Content-Disposition: attachment; filename=$file_name");
header("Content-Length: " . filesize($yourfile));
readfile($yourfile);
unlink('temp/backup.zip');
exit;
?>

我在http://php.net/manual/en/class.recursiveiteratoriterator.php上读到了递归迭代器,这里也有很多问题没有解决。

将./index.php替换为./works,但这包括不希望放在zip中的目录。

任何允许在下载的zip中插入php的输入,非常感谢。

您可以使用FilterIteratorCallbackFilterIterator。如果你在多个地方使用相同的过滤器,最好使用FilterIterator。为简单起见,我使用CallbackFilterIterator并定义过滤器函数,该函数使用preg_match来决定文件是否将出现在循环中。

$path = '../test';
$directories = ['images', 'Data', 'css'];
$filter = function ($current, $key, $iterator) use ($path, $directories) {
    $path = preg_quote($path, '/');
    $directories = implode('|', array_map('preg_quote', $directories));
    if (preg_match('/^' . $path . ''/(' . $directories . ')/', $key)) {
        return true;
    }
    if (preg_match('/^' . $path . '.+'.php$/', $key)) {
        return true;
    }
    return false;
};
$files = new CallbackFilterIterator(
    new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator(
            $path,
            FilesystemIterator::SKIP_DOTS
        ),
        RecursiveIteratorIterator::LEAVES_ONLY
    ),
    $filter
);
foreach ($files as $key => $file) {
    // Do something with files.
    var_dump($key, $file);
}

注意FilesystemIterator::SKIP_DOTS标志。它可以帮助您避免这样的代码:

if ($file->getFilename() != '.' && $file->getFilename() != '..') {
    // ...
}
另一种方法是使用原始代码只添加目录,但对于文件使用ZipArchive::addPattern方法:
$zip->addPattern('/'.(?:php)$/', $path)

注意,模式将只匹配文件名