Архивирование папки с файлами

Тема в разделе "PHP", создана пользователем DIAgen, 30 сен 2008.

Статус темы:
Закрыта.
Модераторы: latteo
  1. DIAgen

    DIAgen Постоялец

    Регистр.:
    30 окт 2006
    Сообщения:
    134
    Симпатии:
    72
    У многих возникает проблема, как можно за архивировать папку с файлами. Вот мое решение, может кому будет полезно

    PHP:
    ini_set('set_time_limit',0); 
    ini_set("memory_limit""528M");
    set_time_limit(0); 
    error_reporting(0); 

    $zipfile = new zipfile(); 
     function 
    _readdir($d,&$files) { 
    global 
    $opendir
    $dir opendir ($d); 
      while ( 
    $file readdir ($dir)) 
      { 
         if (( 
    $file != ".") && ($file != "..")) 

       
    $opendir=$d.'/'.$file
             if(
    filetype($opendir)=="dir"
            { 
            
    _readdir($opendir,&$files); 
            } 
            else 
            { 
             
    $files[] = $opendir

       } 
       } 

       
    closedir ($dir); 
     } 
      
     
    _readdir('/home/',&$files); // ТУт указываем полный путь до папки которую нужно жать.... 
      
      
    foreach ($files as $index) { 
     
    $zipfile -> addFile(file_get_contents($index), $index); 
     } 

    $dump_buffer $zipfile -> file(); // отправляем готовый архив в переменную для экспорта(вывода) 

    header('Content-Type: application/x-zip'); 
    header("Content-Length: ".strlen($dump_buffer)); 
    header('Content-Disposition: attachment; filename="myarchive.zip"'); 
    echo 
    $dump_buffer;  

    class 
    zipfile 


        var 
    $datasec      = array(); 

        var 
    $ctrl_dir     = array(); 

        var 
    $eof_ctrl_dir "\x50\x4b\x05\x06\x00\x00\x00\x00"

        var 
    $old_offset   0


        function 
    unix2DosTime($unixtime 0) { 
            
    $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime); 

            if (
    $timearray['year'] < 1980) { 
                    
    $timearray['year']    = 1980
                    
    $timearray['mon']     = 1
                    
    $timearray['mday']    = 1
                    
    $timearray['hours']   = 0
                    
    $timearray['minutes'] = 0
                    
    $timearray['seconds'] = 0
            } 
    // end if 

            
    return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | 
                    (
    $timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1); 
        } 
    // end of the 'unix2DosTime()' method 
        
    function addFile($data$name$time 0
        { 
            
    $name     str_replace('\\''/'$name); 

            
    $dtime    dechex($this->unix2DosTime($time)); 
            
    $hexdtime '\x' $dtime[6] . $dtime[7
                      . 
    '\x' $dtime[4] . $dtime[5
                      . 
    '\x' $dtime[2] . $dtime[3
                      . 
    '\x' $dtime[0] . $dtime[1]; 
            eval(
    '$hexdtime = "' $hexdtime '";'); 

            
    $fr   "\x50\x4b\x03\x04"
            
    $fr   .= "\x14\x00";            // ver needed to extract 
            
    $fr   .= "\x00\x00";            // gen purpose bit flag 
            
    $fr   .= "\x08\x00";            // compression method 
            
    $fr   .= $hexdtime;             // last mod time and date 

            // "local file header" segment 
            
    $unc_len strlen($data); 
            
    $crc     crc32($data); 
            
    $zdata   gzcompress($data); 
            
    $zdata   substr(substr($zdata0strlen($zdata) - 4), 2); // fix crc bug 
            
    $c_len   strlen($zdata); 
            
    $fr      .= pack('V'$crc);             // crc32 
            
    $fr      .= pack('V'$c_len);           // compressed filesize 
            
    $fr      .= pack('V'$unc_len);         // uncompressed filesize 
            
    $fr      .= pack('v'strlen($name));    // length of filename 
            
    $fr      .= pack('v'0);                // extra field length 
            
    $fr      .= $name

            
    // "file data" segment 
            
    $fr .= $zdata

            
    // "data descriptor" segment (optional but necessary if archive is not 
            // served as file) 
            
    $fr .= pack('V'$crc);                 // crc32 
            
    $fr .= pack('V'$c_len);               // compressed filesize 
            
    $fr .= pack('V'$unc_len);             // uncompressed filesize 

            // add this entry to array 
            
    $this -> datasec[] = $fr

            
    // now add to central directory record 
            
    $cdrec "\x50\x4b\x01\x02"
            
    $cdrec .= "\x00\x00";                // version made by 
            
    $cdrec .= "\x14\x00";                // version needed to extract 
            
    $cdrec .= "\x00\x00";                // gen purpose bit flag 
            
    $cdrec .= "\x08\x00";                // compression method 
            
    $cdrec .= $hexdtime;                 // last mod time & date 
            
    $cdrec .= pack('V'$crc);           // crc32 
            
    $cdrec .= pack('V'$c_len);         // compressed filesize 
            
    $cdrec .= pack('V'$unc_len);       // uncompressed filesize 
            
    $cdrec .= pack('v'strlen($name) ); // length of filename 
            
    $cdrec .= pack('v');             // extra field length 
            
    $cdrec .= pack('v');             // file comment length 
            
    $cdrec .= pack('v');             // disk number start 
            
    $cdrec .= pack('v');             // internal file attributes 
            
    $cdrec .= pack('V'32 );            // external file attributes - 'archive' bit set 

            
    $cdrec .= pack('V'$this -> old_offset ); // relative offset of local header 
            
    $this -> old_offset += strlen($fr); 

            
    $cdrec .= $name

            
    // optional extra field, file comment goes here 
            // save to central directory 
            
    $this -> ctrl_dir[] = $cdrec
        } 
    // end of the 'addFile()' method 
        
    function file() 
        { 
            
    $data    implode(''$this -> datasec); 
            
    $ctrldir implode(''$this -> ctrl_dir); 

            return 
                
    $data 
                
    $ctrldir 
                
    $this -> eof_ctrl_dir 
                
    pack('v'sizeof($this -> ctrl_dir)) .  // total # of entries "on this disk" 
                
    pack('v'sizeof($this -> ctrl_dir)) .  // total # of entries overall 
                
    pack('V'strlen($ctrldir)) .           // size of central dir 
                
    pack('V'strlen($data)) .              // offset to start of central dir 
                
    "\x00\x00";                             // .zip file comment length 
        
    // end of the 'file()' method 

    // end of the 'zipfile' class
     
    Xe-Xe, Prescott, Liver и 2 другим нравится это.
  2. oneathome

    oneathome

    Регистр.:
    6 фев 2007
    Сообщения:
    159
    Симпатии:
    5
    DIAgen! Попробовал на Денвере код в работе, все ОК!

    Создал файл php, положил его в категорию и указал, что надо сжать папку administrator (без указания пути).

    Спасибо!
     
  3. DIAgen

    DIAgen Постоялец

    Регистр.:
    30 окт 2006
    Сообщения:
    134
    Симпатии:
    72
    Надо будет вставить этот код в r57, а то часто бывает что системными фунциями не получаеться заархивировать файлы.
     
  4. a_n_d_y

    a_n_d_y

    Регистр.:
    26 мар 2006
    Сообщения:
    465
    Симпатии:
    61
    Я как-то сам не заморачивался над написанием своего класса, вполне pclzip хватает.
    PHP:
                $arc 'newarc.zip';
                
    //Создаем пустой архив
                
    $archive = new PclZip($arc);
                
    $d dir($dirtoread);// Читаем папку, вполне хватает и относительного пути
                
    while (false !== ($entry $d->read())) {
                    if (
    $entry == '.' || $entry == '..')
                        continue;
                    
    $file $dirtoread.$entry;
                    
    $archive->add($filePCLZIP_OPT_REMOVE_PATH$dirtoread);//Добавляем файл в архив, тут я удаляю имя папки из пути, но можно и оставить
                
    }
                
    $d->close();
     
  5. Yaggi Jah

    Yaggi Jah Постоялец

    Регистр.:
    15 ноя 2006
    Сообщения:
    75
    Симпатии:
    31
    А что rar уже не в моде?
    PHP:
    exec('rar a архив.rar путь_к_катологу -m5 -p[пароль_если_надо]');
     
  6. BACZ

    BACZ

    Регистр.:
    18 июн 2008
    Сообщения:
    612
    Симпатии:
    386
    rar может и в моде, а exec - нет; на большинстве массовых хостингов exec как и passthru, system и прочие shell_exec-и загорают в disable_functions

    Распаковщик и запаковщик папок на основе pclzip.lib.php можно взять здесь
    там внутри и сама либа в каждом архиве

    http://fdstar.net/fde/datas/2008/03/27/1206621852/archivator.zip
    http://fdstar.net/fde/datas/2008/03/27/1206621257/archive_extractor.zip

    пакер там примерно такой
    PHP:
    <?PHP
    $name_arch
    ='/home/user1/domain/site.ru/public_html/zipfolder/archive.zip';
    require_once 
    '/home/user1/domain/site.ru/public_html/zipfolder/include/pclzip.lib.php';
    //echo $filesdir=trim(realpath(dirname($_SERVER['SCRIPT_FILENAME'])),'/');
    chdir('/home/user1/domain/site.ru/public_html');        
    $files_to_arch=array();
    $filesdir='.';
    for(
    $d=@opendir($filesdir);$file=@readdir($d);)
    {      
        if(
    $file!='.' && $file!='..' && $file!='..'
            
    $files_to_arch[]=str_replace('./','',$filesdir.'/'.$file);
    }
    $archive=new PclZip($name_arch);
    //$v_list=$archive->create(implode(',',$files_to_arch),
    //                        PCLZIP_OPT_REMOVE_PATH,
    //                        $filesdir);
    $v_list=$archive->create(implode(',',$files_to_arch));
    if(
    $v_list==0)
       die(
    "Error : ".$archive->errorInfo(true));
    else
       echo 
    'OK';
    ?>
     
  7. PHP_Master

    PHP_Master

    Регистр.:
    3 фев 2008
    Сообщения:
    2.647
    Симпатии:
    591
    rar на nix'овом хостинге? Ты часто такое встречал?

    PHP:
    ini_set("memory_limit""528M"); 
    За такое можно и по гриве отгрести (на хостинге), если вообще дадут сделать :D

    Кстати в 5.3 встроена поддержка архиваторов в ядро.
     
  8. DIAgen

    DIAgen Постоялец

    Регистр.:
    30 окт 2006
    Сообщения:
    134
    Симпатии:
    72
    В php5 есть поддержка rar но только на чтение архива и разархивирование.

    PHP:
    ini_set("memory_limit""528M"); 
    это я сделал из-за того что по стандарту memory_limit установлен 8 или 16 мегабайт на выполнение, и при попытке заархивировать папку которая больше 30-50 метров выдает на не хватку памяты для выполнения.

    Это хорошо что в php 5.3 уже строен архиватор в ядро, вот только загвозка в том что хостеры обновляют ядро редко, обычно стоит ядно 5.2
     
  9. Yaggi Jah

    Yaggi Jah Постоялец

    Регистр.:
    15 ноя 2006
    Сообщения:
    75
    Симпатии:
    31
    Так для справки
    http://www.rarlab.com/download.htm
     
  10. a_n_d_y

    a_n_d_y

    Регистр.:
    26 мар 2006
    Сообщения:
    465
    Симпатии:
    61
    Кстати на phpclub где-то статья была о реализации rar на сервере...
     
Статус темы:
Закрыта.