zip存档是什么样的,我们可以怎么做

美好的一天,亲爱的哈伯!

在过去的半年中,我的宠物项目弯曲的路把我带入了这样的丛林,从那里仍然无法脱身。 一切都以无害的方式开始-一个有图片的网站,但是一种完美主义的感觉,对免费赠品的追求以及我心态的某些特征,使这一切按原计划进行,实际上是一段漫长的旅程。 好吧,好吧,正如一位颇为埋葬的革命家曾经说过的:“再次学习,学习”,但我(故意)要遵循这种告诫。

哦,我们从主要话题上分散了注意力。 我不会再冗长的演讲让您厌烦,但我会开始做事。

创建一个zip存档


原则上,我不会在这里重写规范 。 总体而言,描述结构也是没有意义的,因为所有这些工作都是在我之前完成的

对于那些懒得跟随链接的人,我将简要概述所有zip归档文件应包含:

  • 文件输入:
    • 本地文件头
    • 有用的数据
    • 数据描述符(可选,当我们不知道文件大小及其哈希值直到将其读取到最后时使用)
  • 中央目录文件标题(用于每个文件。就像书的目录,其中指出了可以在其中找到的每个部分和页面)
  • 中央目录的结尾

知道了这一点,我们可以尝试编写一个仅包含两个文件的简单存档:

<?php //        (1.txt  2.txt)   : $entries = [ '1.txt' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc id ante ultrices, fermentum nibh eleifend, ullamcorper nunc. Sed dignissim ut odio et imperdiet. Nunc id felis et ligula viverra blandit a sit amet magna. Vestibulum facilisis venenatis enim sed bibendum. Duis maximus felis in suscipit bibendum. Mauris suscipit turpis eleifend nibh commodo imperdiet. Donec tincidunt porta interdum. Aenean interdum condimentum ligula, vitae ornare lorem auctor in. Suspendisse metus ipsum, porttitor et sapien id, fringilla aliquam nibh. Curabitur sem lacus, ultrices quis felis sed, blandit commodo metus. Duis tincidunt vel mauris at accumsan. Integer et ipsum fermentum leo viverra blandit.', '2.txt' => 'Mauris in purus sit amet ante tempor finibus nec sed justo. Integer ac nibh tempus, mollis sem vel, consequat diam. Pellentesque ut condimentum ex. Praesent finibus volutpat gravida. Vivamus eleifend neque sit amet diam scelerisque lacinia. Nunc imperdiet augue in suscipit lacinia. Curabitur orci diam, iaculis non ligula vitae, porta pellentesque est. Duis dolor erat, placerat a lacus eu, scelerisque egestas massa. Aliquam molestie pulvinar faucibus. Quisque consequat, dolor mattis lacinia pretium, eros eros tempor neque, volutpat consectetur elit elit non diam. In faucibus nulla justo, non dignissim erat maximus consectetur. Sed porttitor turpis nisl, elementum aliquam dui tincidunt nec. Nunc eu enim at nibh molestie porta ut ac erat. Sed tortor sem, mollis eget sodales vel, faucibus in dolor.', ]; //      Lorem.zip,      cwd (      ) $destination = 'Lorem.zip'; $handle = fopen($destination, 'w'); //      ,    ,     ,   "" Central Directory File Header $written = 0; $dictionary = []; foreach ($entries as $filename => $content) { //         Local File Header,     //        ,      . $fileInfo = [ //     'versionToExtract' => 10, //   0,        - 'generalPurposeBitFlag' => 0, //      ,    0 'compressionMethod' => 0, // -    mtime ,    ,      ? 'modificationTime' => 28021, //   , ? 'modificationDate' => 20072, //      .     ,       ,   ? 'crc32' => hexdec(hash('crc32b', $content)), //     .        . //       :) 'compressedSize' => $size = strlen($content), 'uncompressedSize' => $size, //    'filenameLength' => strlen($filename), //  .    ,   0. 'extraFieldLength' => 0, ]; //      . $LFH = pack('LSSSSSLLLSSa*', ...array_values([ 'signature' => 0x04034b50, //  Local File Header ] + $fileInfo + ['filename' => $filename])); //       ,       Central Directory File Header $dictionary[$filename] = [ 'signature' => 0x02014b50, //  Central Directory File Header 'versionMadeBy' => 798, //  .    ,  -  . ] + $fileInfo + [ 'fileCommentLength' => 0, //    . No comments 'diskNumber' => 0, //     0,        'internalFileAttributes' => 0, //    'externalFileAttributes' => 2176057344, //    'localFileHeaderOffset' => $written, //      Local File Header 'filename' => $filename, //  . ]; //      $written += fwrite($handle, $LFH); //    $written += fwrite($handle, $content); } // ,     ,    . //          End of central directory record (EOCD) $EOCD = [ //  EOCD 'signature' => 0x06054b50, //  .    ,   0 'diskNumber' => 0, //      -  0 'startDiskNumber' => 0, //       . 'numberCentralDirectoryRecord' => $records = count($dictionary), //    .    ,     'totalCentralDirectoryRecord' => $records, //   Central Directory Record. //      ,      'sizeOfCentralDirectory' => 0, // ,    Central Directory Records 'centralDirectoryOffset' => $written, //     'commentLength' => 0 ]; //     !   foreach ($dictionary as $entryInfo) { $CDFH = pack('LSSSSSSLLLSSSSSLLa*', ...array_values($entryInfo)); $written += fwrite($handle, $CDFH); } // ,   .  ,    $EOCD['sizeOfCentralDirectory'] = $written - $EOCD['centralDirectoryOffset']; //     End of central directory record $EOCD = pack('LSSSSLLS', ...array_values($EOCD)); $written += fwrite($handle, $EOCD); //  . fclose($handle); echo '  : ' . $written . ' ' . PHP_EOL; echo '     `unzip -tq ' . $destination . '`' . PHP_EOL; echo PHP_EOL; 

尝试运行此原始代码,输出将为您提供一个Lorem.zip文件,其中将包含1.txt和2.txt。

怎么了


当然,任何适当的人都会说用php编写存档器是徒劳的,特别是因为对于诸如zip这样的格式,有很多现成的实现可以满足每种口味和颜色。 并且在相同的php中有现成的库。 我也会说:)

但是,为什么是整篇文章,为什么我花时间写这篇文章,而您却阅读呢?
然后,一切都不是那么简单,并且知道zip的工作原理,这为我们带来了更多的可能性。

首先,我希望至少能有所帮助,但对希望了解zip结构的人有所帮助。
其次,我们用自己的双手创建档案,我们可以控制并且最重要的是可以访问其内部数据。

我们可以预先计算“本地文件头”和“中央目录文件头”,然后按需即时生成包含任何内容和文件顺序的zip存档,只需替换这些数据即可。 除了I / O,没有任何开销。

或者,我们可以记录存档,例如将其上传到云中,该云支持分段下载,并且知道每个文件的偏移量,就可以获取任何存档文件,就像它根本不在存档中一样,只添加一个请求的标题。 然后所有这些都可以被代理...

好吧,让我们不要超越自己。 如果您对此主题感兴趣,那么在以下文章中,我将尝试考虑这些机会并展示如何使用它们。


'diskNumber'=> 0,//通常我到处都遇到0,尤其是我决定不去研究
berez所建议,多卷归档中的号。

Source: https://habr.com/ru/post/zh-CN471066/


All Articles