如何使用Codeigniter和PHP从大文件夹创建zip文件?

时间:2018-04-02 09:11:08

标签: php codeigniter zip backup

我试图从一个大小近2GB的大文件夹创建zip文件。我的代码在localhost上运行良好,但它不能在服务器上运行(Cpanel)。在服务器中,它创建了一个zip文件,其大小只有2GB的103 MB。根据我的策略,首先,我创建一个递归命名为" system_backup"的备份文件夹。备份文件夹创建顺利,没有任何问题。接下来是,创建' system_backup'的zip文件。通过调用ZipData函数将文件夹存储到另一个文件夹中。在这段时间内,它没有正确创建zip文件。

之后,将调用 rrmdir 功能。它将删除' system_backup'文件夹递归。并且删除也不正常。并且,在localhost中,它运行良好。

然后,当我尝试通过 download_file 功能下载创建的zip文件时,它也无法正常下载。它被下载为损坏的zip文件。并且,在localhost中,它也运行良好。

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

代码如下: -

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 */

1 个答案:

答案 0 :(得分:0)

以下代码使用的是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行&amp; 6用于将文件添加到zip文件

第9行用于将名为random.txt的文件添加到zip文件中,并在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文件