Richie: zip - on the fly

Beitrag lesen

Hallo zusammen,

ich möchte 'on the fly' mehrer Dateien in einem zip archive speichern.
Habe eine passende Klasse bei Zend gefunden:
http://www.zend.com/codex.php?id=696&single=1

Leider wird bei meiner Umsetzung nur ein leeres zip archive generiert.
Die zu packende Datei datei.txt ist im gleichen Verzeichnis wie das Script.

Kann jemand vielleicht einen Fehler entdecken?
OS=Suse web-edition 7

<?php
class zipfile
{

var $datasec = array(); // array to store compressed data
    var $ctrl_dir = array(); // central directory
    var $eof_ctrl_dir = "x50x4bx05x06x00x00x00x00"; //end of Central directory record
    var $old_offset = 0;

function add_dir($name)

// adds "directory" to archive - do this before putting any files in directory!
    // $name - name of directory... like this: "path/"
    // ...then you can add files using add_file with names like "path/file.txt"
    {
        $name = str_replace("\", "/", $name);

$fr = "x50x4bx03x04";
        $fr .= "x0ax00";    // ver needed to extract
        $fr .= "x00x00";    // gen purpose bit flag
        $fr .= "x00x00";    // compression method
        $fr .= "x00x00x00x00"; // last mod time and date

$fr .= pack("V",0); // crc32
        $fr .= pack("V",0); //compressed filesize
        $fr .= pack("V",0); //uncompressed filesize
        $fr .= pack("v", strlen($name) ); //length of pathname
        $fr .= pack("v", 0 ); //extra field length
        $fr .= $name;
        // end of "local file header" segment

// no "file data" segment for path

// "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;

$new_offset = strlen(implode("", $this->datasec));

// ext. file attributes mirrors MS-DOS directory attr byte, detailed
        // at http://support.microsoft.com/support/kb/articles/Q125/0/19.asp

// now add to central record
        $cdrec = "x50x4bx01x02";
        $cdrec .="x00x00";    // version made by
        $cdrec .="x0ax00";    // version needed to extract
        $cdrec .="x00x00";    // gen purpose bit flag
        $cdrec .="x00x00";    // compression method
        $cdrec .="x00x00x00x00"; // last mod time & date
        $cdrec .= pack("V",0); // crc32
        $cdrec .= pack("V",0); //compressed filesize
        $cdrec .= pack("V",0); //uncompressed filesize
        $cdrec .= pack("v", strlen($name) ); //length of filename
        $cdrec .= pack("v", 0 ); //extra field length
        $cdrec .= pack("v", 0 ); //file comment length
        $cdrec .= pack("v", 0 ); //disk number start
        $cdrec .= pack("v", 0 ); //internal file attributes
        $ext = "x00x00x10x00";
        $ext = "xffxffxffxff";
        $cdrec .= pack("V", 16 ); //external file attributes  - 'directory' bit set

$cdrec .= pack("V", $this -> old_offset ); //relative offset of local header
        $this -> old_offset = $new_offset;

$cdrec .= $name;
        // optional extra field, file comment goes here
        // save to array
        //$this -> ctrl_dir[] = $cdrec;
        $this -> ctrl_dir[] = $cdrec) ;

}

function add_file($data, $name)

// adds "file" to archive
    // $data - file contents
    // $name - name of file in archive. Add path if your want

{
        $name = str_replace("", "/", $name);
        //$name = str_replace("", "", $name);

$fr = "x50x4bx03x04";
        $fr .= "x14x00";    // ver needed to extract
        $fr .= "x00x00";    // gen purpose bit flag
        $fr .= "x08x00";    // compression method
        $fr .= "x00x00x00x00"; // last mod time and date

$unc_len = strlen($data);
        $crc = crc32($data);
        $zdata = gzcompress($data);
        $zdata = substr( substr($zdata, 0, strlen($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;
        // end of "local file header" segment

// "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;

$new_offset = strlen(implode("", $this->datasec));

// now add to central directory record
        $cdrec = "x50x4bx01x02";
        $cdrec .="x00x00";    // version made by
        $cdrec .="x14x00";    // version needed to extract
        $cdrec .="x00x00";    // gen purpose bit flag
        $cdrec .="x08x00";    // compression method
        $cdrec .="x00x00x00x00"; // 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", 0 ); //extra field length
        $cdrec .= pack("v", 0 ); //file comment length
        $cdrec .= pack("v", 0 ); //disk number start
        $cdrec .= pack("v", 0 ); //internal file attributes
        $cdrec .= pack("V", 32 ); //external file attributes - 'archive' bit set

$cdrec .= pack("V", $this -> old_offset ); //relative offset of local header
//        echo "old offset is ".$this->old_offset.", new offset is $new_offset<br>";
        $this -> old_offset = $new_offset;

$cdrec .= $name;
        // optional extra field, file comment goes here
        // save to central directory
        $this -> ctrl_dir[] = $cdrec);
    }

function file() { // dump out 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
            "x00x00";                             // .zip file comment length
    }
}

$zipfile = new zipfile();
// add the subdirectory ... important!
$direc="datei/";
$zipfile -> add_dir($direc);
// add the binary data stored in the string 'filedata'
$path="./datei.txt";

if(is_file($path)) {
   $fp = fopen ($path, "rb") or die("fehler01");
   $filedata = fread ($fp, filesize($path));
   $zipfile -> add_file($filedata, "datei/datei.txt") or die("fehler02");
   fclose($fp);

}else{
                           die("nofile");
                         }

// the next three lines force an immediate download of the zip file:
header("Content-type: application/octet-stream");
header("Content-disposition: attachment; filename=output.zip");
$zipfile -> file();
?>
Gruß Richie