Я должен изменить свой старый php-код, чтобы обновить нашу вики до 1.28.
У меня есть плагин экспорта, который сохраняет выбранные страницы в строки.
эта строка добавляется в zip-файл и сжимается gzcompress.
Я могу скачать файл, но когда я пытаюсь открыть его, он говорит: «Файл поврежден». Если я восстановлю архив с помощью winrar, я получу ожидаемый выходной файл. Как я могу решить, чтобы получить правильный .zipfile в первую очередь
Это может иметь какое-то отношение к старому 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
}
Вы путаете разные форматы файлов. РНР gzcompress
создает формат zlib, тогда как вы пытаетесь интерпретировать его как файл в формате .zip, а это не так.
Кроме того, названия этих функций в PHP ужасны и вводят в заблуждение, поскольку кто-то может подумать, что gzcompress
будет производить формат GZIP. (Что, кстати, тоже не формат zip.) Но нет, gzcompress
производит формат zlib Если вы хотите формат GZIP, вам нужно использовать gzencode
, Если вам нужен формат raw deflate, тогда вам нужно использовать gzdeflate
, Итак, три функции начинаются с gz
, но только один производит формат GZIP.
Ни один из них не производит формат почтового индекса. Для этого, как отмечает symcbean, вы должны использовать ZipArchive класс.
Других решений пока нет …