bituniverse.com Foren-Übersicht bituniverse.com
Entwickler Forum
 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen   RegistrierenRegistrieren 
 ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Zip-Archive erstellen

 
Neues Thema eröffnen   Neue Antwort erstellen    bituniverse.com Foren-Übersicht -> Code-Schnipsel
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Jens
Administrator


Anmeldedatum: 05.11.2007
Beiträge: 193

BeitragVerfasst am: Fr 07 Dez, 2007 11:14    Titel: Zip-Archive erstellen Antworten mit Zitat

Diese Klasse ist aus dem Wunsch heraus entstanden, auch größere Zip-Archive online erstellen zu können. Sie basiert auf der Zip-Library von PHPMyAdmin.

Damit sollte es eigentlich möglich sein, auch bei kleinerem oder fixem memory_limit noch ein Zip-Archiv raus zu pusten.

Php:
  1. <?php
  2. /**
  3.  * This class is an adaption of a zip library from phpmyadmin v2.4.
  4.  * PHPMyAdmin was released under the terms of GPLv2.
  5.  *
  6.  * The origins and license of this library itself are pretty unclear.
  7.  * For the moment we can only assume, that the GPLv2 is the correct
  8.  * license for all this.
  9.  *
  10.  * This adaption of a library therfor is released on the same terms
  11.  * as stated by the phpmyadmin project.
  12.  *
  13.  * For a complete copy of the license agreement please see either
  14.  * www.gnu.org or
  15.  *
  16.  * All adaptions where made by Jens Clasen <juwe@clasennet.de>.
  17.  * This file was submitted to the phpmyadmin project and published
  18.  *
  19.  * The author kindly asks to keep the link and author name in place
  20.  * when using this adaption in other projects.
  21.  *
  22.  * ####### Original header & Credits #########
  23.  *
  24.  * Zip file creation class.
  25.  * Makes zip files.
  26.  *
  27.  * Based on :
  28.  *
  29.  *  http://www.zend.com/codex.php?id=535&single=1
  30.  *  By Eric Mueller <eric@themepark.com>
  31.  *
  32.  *  http://www.zend.com/codex.php?id=470&single=1
  33.  *  by Denis125 <webmaster@atlant.ru>
  34.  *
  35.  *  a patch from Peter Listiak <mlady@users.sourceforge.net> for last modified
  36.  *  date and time of the compressed file
  37.  *
  38.  * Official ZIP file format: www.pkware.com
  39.  *
  40.  * @access  public
  41.  */
  42. class zipfile
  43. {
  44.  
  45.     /**
  46.      * flag to show if further records can be attached to this archiv.
  47.      * @var bool can_take_records
  48.      */
  49.     var $can_take_records=true;
  50.  
  51.     /**
  52.      * central directory record count
  53.      * @var int $cd_record_cnt;
  54.      */
  55.     var $cd_record_cnt=0;
  56.  
  57.     /**
  58.      * End of central directory record
  59.      *
  60.      * @var  string   $eof_ctrl_dir
  61.      */
  62.     var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
  63.  
  64.     /**
  65.      * Last offset position
  66.      *
  67.      * @var  integer  $old_offset
  68.      */
  69.     var $old_offset   = 0;
  70.  
  71.  
  72.     /**
  73.      * File descriptor for temporary storage of data segments
  74.      * @var ressource $data_fd
  75.      */
  76.     var $data_fd           = null;
  77.  
  78.     /**
  79.      * File descriptor for temporary storage of central directory
  80.      * @var ressource $directory_fd
  81.      */
  82.     var $directory_fd      = null;
  83.  
  84.  
  85.     /**
  86.      * total amount of raw data
  87.      * @var float $data_size
  88.      */
  89.     var $data_size         = 0;
  90.  
  91.     /**
  92.      * total amount of data in central directory
  93.      * @var float $cd_size
  94.      */
  95.     var $cd_size           = 0;
  96.  
  97.     /**
  98.      * Prepares temporary files for storing data segments and central directory
  99.      * @access private
  100.      */
  101.     function prepareTempfiles()
  102.     {
  103.       if(!is_resource($this->data_fd))
  104.         $this->data_fd=tmpfile();
  105.  
  106.       if(!is_resource($this->directory_fd))
  107.         $this->directory_fd=tmpfile();
  108.     }
  109.  
  110.     /**
  111.      * Converts an Unix timestamp to a four byte DOS date and time format (date
  112.      * in high two bytes, time in low two bytes allowing magnitude comparison).
  113.      *
  114.      * @param  integer  the current Unix timestamp
  115.      *
  116.      * @return integer  the current date in a four byte DOS format
  117.      *
  118.      * @access private
  119.      */
  120.     function unix2DosTime($unixtime = 0) {
  121.         $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
  122.  
  123.         if ($timearray['year'] < 1980) {
  124.             $timearray['year']    = 1980;
  125.             $timearray['mon']     = 1;
  126.             $timearray['mday']    = 1;
  127.             $timearray['hours']   = 0;
  128.             $timearray['minutes'] = 0;
  129.             $timearray['seconds'] = 0;
  130.         } // end if
  131.  
  132.         return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
  133.                 ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
  134.     } // end of the 'unix2DosTime()' method
  135.  
  136.     /**
  137.      * This method marks an archive as complete and ready for sending.
  138.      * @access private
  139.      */    
  140.     function markComplete()
  141.     {
  142.       $this->can_take_records=false;
  143.       rewind($this->data_fd);
  144.       rewind($this->directory_fd);
  145.     }
  146.  
  147.     /**
  148.      * Returns zip archiv "footer"
  149.      * @access private
  150.      */
  151.     function getFooter()
  152.     {
  153.       if($this->can_take_records)
  154.       {
  155.         trigger_error('This zip archiv was not marked complete. Footer can not be created'
  156.                       .' when further records might be attached later!',
  157.                       E_USER_ERROR);
  158.         return;
  159.       }
  160.  
  161.       return $this -> eof_ctrl_dir .
  162.              pack('v', $this -> cd_record_cnt)     .              // total # of entries "on this disk"
  163.              pack('v', $this -> cd_record_cnt)     .              // total # of entries overall
  164.              pack('V', $this->cd_size)             .              // size of central dir
  165.              pack('V', $this->data_size)           .              // offset to start of central dir
  166.              "\x00\x00";                                          // .zip file comment length
  167.     }
  168.     /**
  169.      * Adds "file" to archive
  170.      *
  171.      * @param  string   file contents
  172.      * @param  string   name of the file in the archive (may contains the path)
  173.      * @param  integer  the current timestamp
  174.      *
  175.      * @access public
  176.      */
  177.     function addFile($data, $name, $time = 0)
  178.     {
  179.         if(!$this->can_take_records)
  180.         {
  181.           trigger_error('This zip archiv was allready marked complete. No further files can be attached!',E_USER_ERROR);
  182.           return;
  183.         }
  184.         $this->prepareTempfiles();
  185.  
  186.         $name     = str_replace('\\', '/', $name);
  187.  
  188.         $dtime    = dechex($this->unix2DosTime($time));
  189.         $hexdtime = '\x' . $dtime[6] . $dtime[7]
  190.                   . '\x' . $dtime[4] . $dtime[5]
  191.                   . '\x' . $dtime[2] . $dtime[3]
  192.                   . '\x' . $dtime[0] . $dtime[1];
  193.         eval('$hexdtime = "' . $hexdtime . '";');
  194.  
  195.         // store position in data file for later usage:
  196.         $data_segment_start_pos=ftell($this->data_fd);
  197.  
  198.         fputs($this->data_fd,"\x50\x4b\x03\x04");
  199.         fputs($this->data_fd,"\x14\x00");            // ver needed to extract
  200.         fputs($this->data_fd,"\x00\x00");            // gen purpose bit flag
  201.         fputs($this->data_fd,"\x08\x00");            // compression method
  202.         fputs($this->data_fd,$hexdtime);             // last mod time and date
  203.  
  204.         // "local file header" segment
  205.         $unc_len = strlen($data);
  206.         $crc     = crc32($data);
  207.         $zdata   = gzcompress($data);
  208.        
  209.         // $data uses quite a lot of memory. Since we don't need it any longer,
  210.         // we can safely remove it at this point.
  211.         unset($data);
  212.  
  213.         $zdata   = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
  214.         $c_len   = strlen($zdata);
  215.         fputs($this->data_fd,pack('V', $crc));             // crc32
  216.         fputs($this->data_fd,pack('V', $c_len));           // compressed filesize
  217.         fputs($this->data_fd,pack('V', $unc_len));         // uncompressed filesize
  218.         fputs($this->data_fd,pack('v', strlen($name)));    // length of filename
  219.         fputs($this->data_fd,pack('v', 0));                // extra field length
  220.         fputs($this->data_fd,$name);
  221.  
  222.         // "file data" segment
  223.         fputs($this->data_fd,$zdata);
  224.  
  225.         // $zdata is quite large as well, therfor we better remove it
  226.         unset($zdata);
  227.  
  228.         // store size for later usage
  229.         $data_segment_length=ftell($this->data_fd)-$data_segment_start_pos;
  230.  
  231.         // now add to central directory record
  232.         fputs($this->directory_fd, "\x50\x4b\x01\x02");
  233.         fputs($this->directory_fd, "\x00\x00");                // version made by
  234.         fputs($this->directory_fd, "\x14\x00");                // version needed to extract
  235.         fputs($this->directory_fd, "\x00\x00");                // gen purpose bit flag
  236.         fputs($this->directory_fd, "\x08\x00");                // compression method
  237.         fputs($this->directory_fd, $hexdtime);                 // last mod time & date
  238.         fputs($this->directory_fd, pack('V', $crc));           // crc32
  239.         fputs($this->directory_fd, pack('V', $c_len));         // compressed filesize
  240.         fputs($this->directory_fd, pack('V', $unc_len));       // uncompressed filesize
  241.         fputs($this->directory_fd, pack('v', strlen($name) )); // length of filename
  242.         fputs($this->directory_fd, pack('v', 0 ));             // extra field length
  243.         fputs($this->directory_fd, pack('v', 0 ));             // file comment length
  244.         fputs($this->directory_fd, pack('v', 0 ));             // disk number start
  245.         fputs($this->directory_fd, pack('v', 0 ));             // internal file attributes
  246.         fputs($this->directory_fd, pack('V', 32 ));            // external file attributes - 'archive' bit set
  247.  
  248.         fputs($this->directory_fd, pack('V', $this -> old_offset )); // relative offset of local header
  249.         $this -> old_offset += $data_segment_length;
  250.  
  251.         fputs($this->directory_fd, $name);
  252.  
  253.         // optional extra field, file comment goes here
  254.         // save to central directory
  255.         $this -> cd_record_cnt++;
  256.        
  257.         // update sizes
  258.         $this->cd_size=ftell($this->directory_fd);
  259.         $this->data_size=ftell($this->data_fd);
  260.  
  261.     } // end of the 'addFile()' method
  262.    
  263.  
  264.     /**
  265.      * Dumps out file (only kept for backwards compatibility)
  266.      *
  267.      * @return  string  the zipped file
  268.      *
  269.      * @access public
  270.      */
  271.     function file()
  272.     {
  273.         $this->prepareTempfiles();
  274.         $this->markComplete();
  275.         return
  276.             fread($this->data_fd,$this->data_size).
  277.             fread($this->directory_fd,$this->cd_size).
  278.             $this->getFooter();
  279.     } // end of the 'file()' method
  280.  
  281.     /**
  282.      * Send zip archive to client
  283.      * @param string $archiveName
  284.      * @access public
  285.      */
  286.     function sendFile($archiveName)
  287.     {
  288.       $this->prepareTempfiles();
  289.       $this->markComplete();
  290.       $footer=$this->getFooter();
  291.  
  292.       header('Content-type: application/x-zip');
  293.       header('Content-disposition: attachment; filename='.$archiveName);
  294.       header('Content-length: '.(strlen($footer)+$this->cd_size+$this->data_size));
  295.       fpassthru($this->data_fd);
  296.       fpassthru($this->directory_fd);
  297.       echo $footer;
  298.     }
  299.  
  300. } // end of the 'zipfile' class
  301. ?>

Beispiel:
Php:
  1. <?php
  2.   $files=array('/path/2/file1.xyz','/path/2/file2.xyz','/path/2/file3.xyz');
  3.   $zip=new zipfile();
  4.   foreach($files as $file)
  5.     $zip->addFile(file_get_contents($file),basename($file),filectime($file));
  6.  
  7.   $zip->sendFile('tst.zip');
  8. ?>

Das ganze ist natürlich nur eine Alternative zu de3.php.net . Grade wenn die Zieplattform feststeht, ist die PHP-Extension evtl. die bessere Alternative.

Gruß Jens

Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Slava
Administrator


Anmeldedatum: 16.01.2007
Beiträge: 284
Wohnort: Köln

BeitragVerfasst am: Fr 07 Dez, 2007 15:00    Titel: Antworten mit Zitat

Super!
Ist es möglich ein Ordner arhivieren?
also wenn ich statt einer Datei ein Ordnername in addFile übergebe?
Danke

Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Jens
Administrator


Anmeldedatum: 05.11.2007
Beiträge: 193

BeitragVerfasst am: Fr 07 Dez, 2007 16:29    Titel: Antworten mit Zitat

Du kannst als Dateinamen durchaus auch irgendwas mit Pfad angeben. Damit ist es dann möglich, ein Verzeichnis rekursiv zu durchlaufen, und die einzelnen Dateien als addFile-Aufruf abzulassen.

Gruß Jens

Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Mannes



Anmeldedatum: 05.11.2007
Beiträge: 24
Wohnort: Gießen

BeitragVerfasst am: Sa 08 Dez, 2007 17:24    Titel: Antworten mit Zitat

Alternativ kann man auch pclZip verwenden, eine Klasse um ZIP-Archive zu erstellen, dateien/ordner hinzufügen, entpacken, auflisten.

Aber auch hier ist man, wie in Jens Lösung, bei grossen Dateien aufgeschmissen. Der memory_limit greift auch hier; Zu grosse Dateien lassen sich also nicht packen.

www.phpconcept.net

Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Jens
Administrator


Anmeldedatum: 05.11.2007
Beiträge: 193

BeitragVerfasst am: So 09 Dez, 2007 20:55    Titel: Antworten mit Zitat

Meine Klasse ist aus einem Thread in einem anderen Forum entstanden, wo das rundherum schon auf die phpmyadmin-Klasse ausgelegt war.

pclZip ist trotzdem echt mal kein schlechter Tipp, insbesondere wenn man was umfassenderes benötigt. Ein kleines bißchen mehr Speicher frisst das Ding allerdings.

Gruß Jens

Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    bituniverse.com Foren-Übersicht -> Code-Schnipsel Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB2.de
Powered by WebRing.