在 PHP 中压缩文件夹的内容

2024-01-01

在将这篇文章标记为重复之前,请注意,我已经在 SO 上搜索过答案,并且到目前为止我发现的一次答案(如下所列)并不完全是我一直在寻找的答案。

  • 如何在 PHP 中[递归地]压缩目录? https://stackoverflow.com/questions/1334613/how-to-recursively-zip-a-directory-in-php
  • 使用 zipArchive addFile() 不会将图像添加到 zip https://stackoverflow.com/questions/5422983/using-ziparchive-addfile-will-not-add-image-to-zip
  • ZipArchive - addFile 不起作用 https://stackoverflow.com/questions/6289456/ziparchive-addfile-wont-work

这些只是我看过的一些。

我的问题是这样的:我不能使用 addFromString,我have要使用 addFile,这是任务的要求。

我已经尝试了几种方法,这是我当前的迭代:

public function getZippedFiles($path)
{
    $real_path = WEBROOT_PATH.$path;

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

    //# create a temp file & open it
    $tmp_file = tempnam($real_path,'');
    $zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file);

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

    foreach ($files as $name=>$file)
    {
        error_log(print_r($name, true));
        error_log(print_r($file, true));
        if ( ($file == ".") || ($file == "..") )
        {
            continue;
        }

        $file_path = $file->getRealPath();
        $zip->addFile($file_path);
    }

    $zip->close();
}

当我尝试打开生成的文件时,我被告知“Windows 无法打开该文件夹。压缩(zipped)文件夹''无效。”

我已经成功使用 addFromString 完成了任务,如下所示:

$file_path = WEBROOT_PATH.$path;
    $files = array();
    if (is_dir($file_path) == true)
    {
        if ($handle = opendir($file_path))
        {
            while (($file = readdir($handle)) !== false)
            {
                if (is_dir($file_path.$file) == false)
                {
                    $files[] = $file_path."\\".$file;
                }
            }

            //# create new zip opbject
            $zip = new ZipArchive();

            //# create a temp file & open it
            $tmp_file = tempnam($file_path,'');
            $zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file);

            $zip->open($zip_file, ZipArchive::CREATE);

            //# loop through each file
            foreach($files as $file){

                //# download file
                $download_file = file_get_contents($file);

                //#add it to the zip
                $zip->addFromString(basename($file),$download_file);

            }

            //# close zip
            $zip->close();
        }
    }
}

上面的内容大部分是直接从我在某处看到的一些示例代码中复制的。如果有人能指出我一个好的方向,我将非常感激!

***** 更新 ***** 我在关闭周围添加了一个 if ,如下所示:

if (!$zip->close()) {
    echo "failed writing zip to archive";
}

该消息得到回显,所以显然问题就在那里。我还检查过以确保$zip->open()有效,并且我已经确认它可以毫无问题地打开它。


终于成功地使用了一些东西addFile.

我创建了一个包含 3 个函数的帮助器类:一个用于列出目录中的所有文件,一个用于压缩所有这些文件,另一个用于下载压缩文件:

<?php
require_once($_SERVER["DOCUMENT_ROOT"]."/config.php");

class FileHelper extends ZipArchive
{
    /**
     * Lists files in dir
     * 
     * This function expects an absolute path to a folder intended as the target.
     * The function will attempt to create an array containing the full paths to 
     * all files in the target directory, except for . and ..
     * 
     * @param dir [string]    : absolute path to the target directory
     * 
     * @return result [array] : array of absolute paths pointing to files in the target directory
     */
    public static function listDirectory($dir)
    {
        $result = array();
        $root = scandir($dir);
        foreach($root as $value) {
            if($value === '.' || $value === '..') {
                continue;
            }
            if(is_file("$dir$value")) {
                $result[] = "$dir$value";
                continue;
            }
            if(is_dir("$dir$value")) {
                $result[] = "$dir$value/";
            }
            foreach(self::listDirectory("$dir$value/") as $value)
            {
                $result[] = $value;
            }
        }
        return $result;
    }

    /**
     * Zips and downloads files
     * 
     * This function expects a directory location as target for a temp file, and a list(array)
     * of absolute file names that will be compressed and added to a zip file. After compression,
     * the temporary zipped file will be downloaded and deleted.
     * 
     * @param location [string] : absolute path to the directory that will contain the temp file
     * @param file_list [array] : array of absolute paths pointing to files that need to be compressed
     * 
     * @return void
     */
    public function downloadZip($file)
    {
        $modules = apache_get_modules();
        if (in_array('mod_xsendfile', $modules)) // Note, it is not possible to detect if X-SendFile is turned on or not, we can only check if the module is installed. If X-SendFile is installed but turned off, file downloads will not work
        {
            header("Content-Type: application/octet-stream");
            header('Content-Disposition: attachment; filename="'.basename($file).'"');
            header("X-Sendfile: ".realpath(dirname(__FILE__)).$file);

            // Apache will take care of the rest, so terminate the script
            exit;
        }

        header("Content-Type: application/octet-stream");
        header("Content-Length: " .(string)(filesize($file)) );
        header('Content-Disposition: attachment; filename="'.basename($file).'"');
        header("Content-Transfer-Encoding: binary");
        header("Expires: 0");
        header("Cache-Control: no-cache, must-revalidate");
        header("Cache-Control: private");
        header("Pragma: public");

        ob_end_clean(); // Without this, the file will be read into the output buffer which destroys memory on large files
        readfile($file);
    }

    /**
     * Zips files
     * 
     * This function expects a directory location as target for a temp file, and a list(array)
     * of absolute file names that will be compressed and added to a zip file. 
     * 
     * @param location [string]  : absolute path to the directory that will contain the temp file
     * @param file_list [array]  : array of absolute paths pointing to files that need to be compressed
     * 
     * @return zip_file [string] : absolute file path of the freshly zipped file
     */
    public function zipFile($location, $file_list)
    {
        $tmp_file = tempnam($location,'');
        $zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file);

        $zip = new ZipArchive();
        if ($zip->open($zip_file, ZIPARCHIVE::CREATE) === true)
        {
            foreach ($file_list as $file)
            {
                if ($file !== $zip_file)
                {
                    $zip->addFile($file, substr($file, strlen($location)));
                }
            }
            $zip->close();
        }

        // delete the temporary files
        unlink($tmp_file);

        return $zip_file;
    }
}
?>

这是我调用此类函数的方式:

$location = "d:/some/path/to/file/";
$file_list = $file_helper::listDirectory($location);
$zip_file = $file_helper->zipFile($location, $file_list);
$file_helper->downloadZip($zip_file);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 PHP 中压缩文件夹的内容 的相关文章

  • Laravel 从 5.6 升级到 Laravel 6

    我有一个项目https github com javedbaloch4 Laravel Booking https github com javedbaloch4 Laravel Booking发展于Laravel 5 6现在我想将其升级到
  • 当数据验证失败时保留表单字段中的值

    我在弄清楚验证失败时如何保留用户数据时遇到问题 我对 PHP 有点陌生 所以我的逻辑可能会犯一些巨大的错误 目前 如果验证失败 所有字段都会被清除 并且 Post 数据也会消失 这是一些代码 假设用户输入无效电子邮件 我希望保留 名称 字段
  • PHP 会话不适用于游戏

    我正在尝试模仿一款名为 SKUNK 用骰子玩 的游戏来完成一项作业 我无法让会话正常工作 这是我第一次使用 PHP 我还被告知无需会议即可完成 这是我的代码
  • 生成大随机数 php [重复]

    这个问题在这里已经有答案了 我想使用 PHP 生成一个包含 75 个字符的数字 我到处寻找 但一无所获 除了这个 http dailycoding com tools RandomNumber aspx http dailycoding c
  • 如何在响应ajax codeigniter后停止执行其他控制器

    我想知道如何在响应输出 json 数据后停止执行函数和涉及的其他控制器 就我这里的情况而言 我只是打电话test 函数于dashboard控制器 In dashboard构造函数将执行MY Login library In MY Login
  • 将“php”作为 shell 脚本执行时的自定义 php.ini 文件

    我在跑php作为 shell 脚本 我不确定 shell脚本 是否正确 该文件以 usr bin php 这很好用 但 MongoDB 类没有正确加载php ini文件 具有extension mongo so 未使用 我该如何使用它tha
  • 是否可以使用 PHP 重定向发送 POST 数据?

    更新 这不是重复的如何使用 PHP 发送 POST 请求 https stackoverflow com questions 5647461 how do i send a post request with php 那里的解决方案对我不起
  • 从 smarty 访问 PHP 文件的变量(本地或全局)

    我有一个 php 文件 其中包含一些本地和全局变量 例如 foo 从此文件中调用 smarty 对象 如何在不更改 PHP 文件的情况下从 smarty 脚本访问 foo Thanks 如果你有一个名为 BASE 的常量变量 并且定义如下
  • 使用 preg_replace 仅替换第一个匹配项

    我有一个结构类似于以下的字符串 aba aaa cba sbd dga gad aaa cbz 该字符串每次都可能有点不同 因为它来自外部源 我只想替换第一次出现的 aaa 但其他人则不然 是否可以 可选的第四个参数预替换 http php
  • 在 PHP 中撤销 Google 访问令牌

    正如标题所示 我想以编程方式撤销授予的访问令牌 即在 PHP 中 我发现这个他们的网站 https developers google com identity protocols OAuth2WebServer tokenrevoke 但
  • PHP 脚本可以在终端中运行,但不能在浏览器中运行

    我正在尝试执行exec命令 但我遇到了问题 当我运行以下代码时 当我通过浏览器运行它时它不起作用 但如果我把输出 str将其复制并粘贴到终端中 它工作得很好 造成这种情况的原因是什么 我该如何解决 目前我正在运行localhost php
  • MySQL 追加字符串

    How can I append a string to the end of an existing table value Let s say I have the table below And let s say that Mari
  • 在 apache docker 容器中运行虚拟主机

    我在同一个 apache 容器中有两个 php 应用程序 我试图在端口上运行其中一个应用程序 因为它需要通过根域而不是子文件夹进行访问 我想在端口 8060 上运行应用程序 我尝试使用 apache 虚拟主机执行此操作 但它不会加载页面 h
  • PHP 中只保留数组的前 N ​​个元素? [复制]

    这个问题在这里已经有答案了 有没有办法只保留数组的前 N 个 例如 10 个 元素 我知道有array pop 但是有没有更好 更优雅的方法呢 您可以使用array slice http php net array slice or arr
  • 使用 Ajax.Request 将 JSON 从浏览器传递到 PHP 的最佳方法

    您好 我有一个 JSON 对象 它是一个二维数组 我需要使用 Ajax Request 将其传递给 PHP 我知道的唯一方法 现在我使用js函数手动序列化我的数组 并获取以下格式的数据 s 1 d 3 4等 我的问题是 有没有办法更直接 有
  • 如果循环中内存超出,我可以在 for 循环中抛出异常吗?

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如何处理 foreach 循环中发生
  • php 错误 fopen(): 文件名不能为空

    发送带有附件代码的电子邮件工作正常 最近我们已将文件传输到另一个托管服务器 idk 发生了什么 它显示以下错误 警告 fopen 第 106 行 home hugerecruitmetnt public html validatecva p
  • 关于 Hadoop 和压缩输入文件的非常基本的问题

    我已经开始研究 Hadoop 如果我的理解是正确的 我可以处理一个非常大的文件 它会被分割到不同的节点上 但是如果文件被压缩 那么文件就无法分割 并且需要由单个节点处理 有效地破坏了运行一个mapreduce 一个并行机器集群 我的问题是
  • Doctrine EntityManager 清除嵌套实体中的方法

    我想用学说批量插入处理 http doctrine orm readthedocs org en latest reference batch processing html为了优化大量实体的插入 问题出在 Clear 方法上 它表示此方法
  • Magento - 自定义支付模块

    这是一个非常普遍的问题 但这里是 我正在尝试在 Magento 中创建一个自定义支付模块 我创建了一个 常规 模块 可以连接到 Magento 事件 观察者模型 但是我如何告诉 Magento 将模块视为支付模块 以便它显示在管理后端和结账

随机推荐