【问题标题】:How to create zip file from a large folder using Codeigniter and PHP?如何使用 Codeigniter 和 PHP 从大文件夹创建 zip 文件?
【发布时间】:2018-04-02 09:11:08
【问题描述】:

我正在尝试从一个大小接近 2GB 的大文件夹创建 zip 文件。我的代码在本地主机上运行良好,但在服务器(Cpanel)上不起作用。在服务器中,它正在创建一个 zip 文件,其大小仅为 2GB 中的 103 MB。根据我的策略,首先,我正在创建一个递归命名为“system_backup”的备份文件夹。并且备份文件夹创建良好,没有任何问题。接下来是通过调用函数 ZipData 创建“system_backup”文件夹的 zip 文件并将其存储到另一个文件夹中。此时,它没有正确创建 zip 文件。

之后,函数rrmdir会被调用。它将递归删除“system_backup”文件夹。并且删除也无法正常工作。而且,在 localhost 中,它运行良好。

然后,当我尝试通过 download_file 函数下载创建的 zip 文件时,它也无法正常下载。它作为损坏的 zip 文件下载。而且,在本地主机中,它也运行良好。

我已经检查了文件夹和文件的读写权限。

代码如下:-

public function backup_app(){
    //Backup System
    ini_set('memory_limit', '-1');
    set_time_limit(0);
    $this->recurse_copy(FCPATH,'system_backup');

    $backup_name = 'Customs-system-backup-on_'. date("Y-m-d-H-i-s") .'.zip';
    $path   = FCPATH.'system_backup';
    $destination = FCPATH.'bdCustomsBackup/'.$backup_name;
    $this->zipData($path, $destination);

    //Delete directory
    $this->rrmdir($path);

    $message = "Application Backup on ".date("Y-m-d-H-i-s");
    $this->submit_log($message);

    echo 1;
}

function zipData($source, $destination) {
    if (extension_loaded('zip')) {
        if (file_exists($source)) {
            $zip = new ZipArchive();
            if ($zip->open($destination, ZIPARCHIVE::CREATE)) {
                $source = realpath($source);
                if (is_dir($source)) {
                    $iterator = new RecursiveDirectoryIterator($source);
                    // skip dot files while iterating 
                    $iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
                    $files = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
                    $counter = 1;
                    foreach ($files as $file) {
                        $file = realpath($file);
                        if (is_dir($file)) {
                            $zip->addEmptyDir(str_replace($source . '/', 'system_backup/', $file . '/'));
                        } else if (is_file($file)) {                                
                            $zip->addFromString(str_replace($source . '/', 'system_backup/', $file), file_get_contents($file));
                        }
                    }
                } else if (is_file($source)) {
                    $zip->addFromString(basename($source), file_get_contents($source));
                }
            }
            return $zip->close();
        }
    }
    return false;
}

public function recurse_copy($src,$dst) { 
    $dir = opendir($src);
    @mkdir($dst); 
    while(false !== ( $file = readdir($dir)) ) {
        if (( $file != '.' ) && ( $file != '..' ) && ( $file != $dst ) && ( $file != "bdCustomsBackup" )) { 
            if ( is_dir($src . '/' . $file) ) { 
                $this->recurse_copy($src . '/' . $file, $dst . '/' . $file); 
            } 
            else { 
                copy($src . '/' . $file,$dst . '/' . $file); 
            } 
        } 
    } 
    closedir($dir); 
}

public function rrmdir($src) {
    $dir = opendir($src);
    while(false !== ( $file = readdir($dir)) ) {
        if (( $file != '.' ) && ( $file != '..' )) {
            $full = $src . '/' . $file;
            if ( is_dir($full) ) {
                $this->rrmdir($full);
            }
            else {
                unlink($full);
            }
        }
    }
    closedir($dir);
    rmdir($src);
}

public function download_file($file){
    $message = "Download ".$file." on ".date("Y-m-d-H-i-s");
    $this->submit_log($message);

    $path = FCPATH.'bdCustomsBackup/'.$file;

    $this->load->helper('download_helper');
    force_download($file, $path);
}

这是自定义 download_helper:-

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

if ( ! function_exists('force_download'))
{
    function force_download($filename = '', $file = '')
    {
        if ($filename == '' OR $file == '')
        {
            return FALSE;
        }

        // Try to determine if the filename includes a file extension.
        // We need it in order to set the MIME type
        if (FALSE === strpos($filename, '.'))
        {
            return FALSE;
        }

        // Grab the file extension
        $x = explode('.', $filename);
        $extension = end($x);

        // Load the mime types
        @include(APPPATH.'config/mimes'.EXT);

        // Set a default mime if we can't find it
        if ( ! isset($mimes[$extension]))
        {
            $mime = 'application/octet-stream';
        }
        else
        {
            $mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
        }

        // Generate the server headers
        if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE)
        {
            header('Content-Type: "'.$mime.'"');
            header('Content-Disposition: attachment; filename="'.$filename.'"');
            header('Expires: 0');
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header("Content-Transfer-Encoding: binary");
            header('Pragma: public');
            header("Content-Length: ".filesize($file));
        }
        else
        {
            header('Content-Type: "'.$mime.'"');
            header('Content-Disposition: attachment; filename="'.$filename.'"');
            header("Content-Transfer-Encoding: binary");
            header('Expires: 0');
            header('Pragma: no-cache');
            header("Content-Length: ".filesize($file));
        }

        readfile_chunked($file);
        die;
    }
}

if ( ! function_exists('readfile_chunked'))
{
    function readfile_chunked($file, $retbytes=TRUE)
    {
       $chunksize = 1 * (1024 * 1024);
       $buffer = '';
       $cnt =0;

       $handle = fopen($file, 'r');
       if ($handle === FALSE)
       {
           return FALSE;
       }

       while (!feof($handle))
       {
           $buffer = fread($handle, $chunksize);
           echo $buffer;
           ob_flush();
           flush();

           if ($retbytes)
           {
               $cnt += strlen($buffer);
           }
       }

       $status = fclose($handle);

       if ($retbytes AND $status)
       {
           return $cnt;
       }

       return $status;
    }
}

/* End of file download_helper.php */
/* Location: ./application/helpers/download_helper.php */

【问题讨论】:

  • PHP 错误日志文件中是否有与问题相关的内容?
  • [02-Apr-2018 00:18:53 America/Chicago] PHP 致命错误:/home/sandboxeasyhost/public_html/bdCustoms 内存不足(已分配 138674176)(尝试分配 215251045 字节) /application/controllers/backup_process.php 在第 86 行。但我使用的是 ini_set('memory_limit', '-1');
  • ini_set('memory_limit', '-1') 表示所有允许的服务器资源。似乎提供商为您提供了 128MB 用于使用过的软件包。
  • 你好 Shoukhin 我在我们说话时遇到了类似的问题。您是否设法找到解决此问题的方法?如果可以,您可以分享您的解决方案吗?

标签: php codeigniter zip backup


【解决方案1】:

以下代码使用 PHP:

    $zip = new ZipArchive;
        if ($zip->open('test_new.zip', ZipArchive::CREATE) === TRUE)
        {
            // Add files to the zip file
            $zip->addFile('test.txt');
            $zip->addFile('test.pdf');

            // Add random.txt file to zip and rename it to newfile.txt
            $zip->addFile('random.txt', 'newfile.txt');

            // Add a file new.txt file to zip using the text specified
            $zip->addFromString('new.txt', 'text to be added to the new.txt file');

            // All files are added, so close the zip file.
            $zip->close();
        }

代码说明

第 1 行创建 ZipArchive 类的对象

第 2 行打开一个文件名为 test_new.zip 的文件,以便我们可以向其中添加文件。 ZipArchive::CREATE 标志指定我们要创建一个新的 zip 文件

第 5 行和第 6 行用于将文件添加到 zip 文件中

第 9 行用于在 zip 文件中添加一个名为 random.txt 的文件,并在 zipfile 中将其重命名为 newfile.txt

第 12 行用于添加新文件 new.txt,文件内容为“要添加到 new.txt 文件中的文本”

第 15 行关闭并将更改保存到 zip 文件

注意:有时在使用文件的相对路径时可能会出现问题。如果使用路径有任何问题,我们也可以使用文件的绝对路径

覆盖现有的 zip 文件

如果您想覆盖现有的 zip 文件,我们可以使用类似于以下的代码。 ZipArchive::OVERWRITE 标志会覆盖现有的 zip 文件。

            $zip = new ZipArchive;
            if ($zip->open('test_overwrite.zip', ZipArchive::OVERWRITE) === TRUE)
            {
                // Add file to the zip file
                $zip->addFile('test.txt');
                $zip->addFile('test.pdf');

                // All files are added, so close the zip file.
                $zip->close();
            }

代码说明

此代码将创建一个文件 test_overwrite.zip,如果该文件已存在,则该文件将被此新文件覆盖

创建一个新的 zip 文件并将文件添加到文件夹中

            $zip = new ZipArchive;
            if ($zip->open('test_folder.zip', ZipArchive::CREATE) === TRUE)
            {
                // Add files to the zip file inside demo_folder
                $zip->addFile('text.txt', 'demo_folder/test.txt');
                $zip->addFile('test.pdf', 'demo_folder/test.pdf');

                // Add random.txt file to zip and rename it to newfile.txt and store in demo_folder
                $zip->addFile('random.txt', 'demo_folder/newfile.txt');

                // Add a file demo_folder/new.txt file to zip using the text specified
                $zip->addFromString('demo_folder/new.txt', 'text to be added to the new.txt file');

                // All files are added, so close the zip file.
                $zip->close();
            }

代码说明

上面的代码将在 zip 文件中添加不同的文件到文件夹 demo_folder 中

addfile 函数的第二个参数可用于将文件存储在新文件夹中

addFromString 函数中的第一个参数可用于将文件存储在新文件夹中

创建一个新的 zip 文件并将文件移动到不同的文件夹中

            $zip = new ZipArchive;
            if ($zip->open('test_folder_change.zip', ZipArchive::CREATE) === TRUE)
            {
                // Add files to the zip file
                $zip->addFile('text.txt', 'demo_folder/test.txt');
                $zip->addFile('test.pdf', 'demo_folder1/test.pdf');

                // All files are added, so close the zip file.
                $zip->close();
            }

代码说明

我们将文件 test.txt 存入 demo_folder,将 test.pdf 存入 demo_folder1

创建一个包含目录中所有文件的 zip 文件

                $zip = new ZipArchive;
                if ($zip->open('test_dir.zip', ZipArchive::OVERWRITE) === TRUE)
                {
                    if ($handle = opendir('demo_folder'))
                    {
                        // Add all files inside the directory
                        while (false !== ($entry = readdir($handle)))
                        {
                            if ($entry != "." && $entry != ".." && !is_dir('demo_folder/' . $entry))
                            {
                                $zip->addFile('demo_folder/' . $entry);
                            }
                        }
                        closedir($handle);
                    }

                    $zip->close();
                }

代码说明

第 5-16 行打开一个目录并创建一个包含该目录中所有文件的 zip 文件

第 5 行打开目录

第 7 行获取目录中每个文件的名称

第 9 行跳过了“.”和“..”以及任何其他目录

第 11 行将文件添加到 zip 文件中

第 14 行关闭目录

第 17 行关闭 zip 文件

【讨论】:

    猜你喜欢
    • 2017-01-17
    • 1970-01-01
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 2012-07-17
    • 2014-01-06
    相关资源
    最近更新 更多