我必须重构一些旧的PHP代码来将我们的wiki更新为1.28。 我有一个Export Plugin,它将所选页面保存为字符串。 此字符串添加到zip文件并由gzcompress压缩。
我可以下载该文件,但是当我尝试打开它时,它会说"文件已损坏"。如果我使用winrar修复存档,我会得到预期的输出文件。如何解决以获得正确的.zip文件
它可能与我们使用的旧ZipHelper有关,但我实际上不知道那里发生了什么,因为我对php很新:
class ZipWriter
{
function __construct()
{
}
var $datasec = array ();
var $ctrl_dir = array ();
var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
var $old_offset = 0;
var $filename = "";
var $filepointer;
var $writtenSizeCtrlDir = 0;
var $writtenSizeData = 0;
var $writtenFiles = 0;
var $completeBuffer;
var $stream = false;
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($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;
// "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
if ($this->stream) {
array_push($this->completeBuffer, $fr);
} else {
// write the compressed data to the zipfile
fputs($this->filepointer, $fr);
}
// count up the already written data size
$this->writtenSizeData = $this->writtenSizeData + strlen($fr);
//$new_offset = strlen(implode('', $this->datasec));
$new_offset = $this->writtenSizeData;
// 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', 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
$this->old_offset = $new_offset;
$cdrec .= $name;
// save to central directory
$this->ctrl_dir[] = $cdrec;
// count up written files
$this->writtenFiles++;
} // end of the 'addFile()' method
}
答案 0 :(得分:2)
您混淆了不同的文件格式。 PHP的gzcompress
生成zlib格式,而您试图将其解释为.zip格式的文件,而不是。
顺便说一下,PHP中这些函数的名称是可怕的和误导性的,因为有人可能会认为gzcompress
会生成gzip格式。 (顺便说一下,不是 zip格式。)但是,不,gzcompress
生成zlib格式。如果您需要gzip格式,则需要使用gzencode
。如果您需要原始deflate格式,则需要使用gzdeflate
。因此,三个函数以gz
开头,但只有一个函数生成gzip格式。
这些都没有产生zip格式。为此,如symcbean所述,您将使用ZipArchive class。