¿Cómo se ve el archivo zip y qué podemos hacer al respecto?

Buen día, querido Habr!

Durante el último medio año, el camino torcido de mis proyectos favoritos me ha llevado a esa jungla, donde todavía parece imposible salir. Y todo comenzó de manera inofensiva: un sitio con imágenes, pero una sensación de perfeccionismo, la búsqueda de un obsequio, así como algunas características de mi mentalidad convirtieron esto, como se había planeado originalmente, en una pequeña caminata en un viaje realmente largo. Bueno, está bien, como solía decir un revolucionario bastante burry: "Aprende, estudia y estudia de nuevo", pero yo, de todos modos, tengo que seguir esta advertencia.

Oh, algo que nos distrajo del tema principal. Ya no te aburriré con largos discursos, pero me dedicaré a los negocios.

Crea un archivo zip


En principio, no volveré a escribir la especificación aquí. En general, tampoco tiene sentido describir la estructura, porque todo esto se hizo antes que yo .

Para aquellos que son demasiado flojos para seguir los enlaces, resumiré brevemente que cualquier archivo zip debe contener:

  • Entrada de archivo:
    • Encabezado de archivo local
    • Datos útiles
    • Descriptor de datos (opcional, utilizado cuando no conocemos el tamaño del archivo y su hash hasta que lo leamos hasta el final)
  • Encabezado del archivo del directorio central (para cada archivo. Esto es como una tabla de contenido del libro, donde se indica cada sección y la página en la que se puede encontrar)
  • Fin del directorio central

Sabiendo esto, podemos intentar escribir un archivo simple que contendrá solo dos archivos:

<?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; 

Intente ejecutar este código primitivo y la salida le dará un archivo Lorem.zip que contendrá 1.txt y 2.txt.

Por qué


Por supuesto, cualquier persona adecuada dirá que escribir archiveros en php es una tarea inútil, especialmente porque para un formato como zip, hay un montón de implementaciones listas para todos los gustos y colores. Y en el mismo php hay bibliotecas listas para usar. Yo también lo diré :)

Pero, ¿por qué, entonces, es todo este artículo, por qué me dediqué a escribirlo y a leerlo?
Y luego, que no todo es tan simple y saber cómo funciona zip, nos abre algunas posibilidades adicionales.

En primer lugar, espero, al menos un poco, pero ayudará a aquellos que quieran comprender la estructura del zip.
Y en segundo lugar, al crear el archivo con nuestras propias manos, tenemos control y, lo más importante, acceso a sus datos internos.

Podemos precalcular el Encabezado de archivo local y el Encabezado de archivo del directorio central y, a pedido, generar un archivo zip sobre la marcha con cualquier contenido y orden de archivos, simplemente sustituyendo estos datos. Y sin gastos generales, excepto para E / S.

O bien, podemos grabar el archivo, subirlo, por ejemplo, a la nube, que admite la descarga fragmentada y, conociendo las compensaciones para cada archivo, obtener cualquiera de los archivos de archivo, como si no estuviera en el archivo, agregando solo uno Título de la solicitud. Y luego todo esto puede ser proxy y ...

De acuerdo, no nos adelantemos. Si está interesado en este tema, en los siguientes artículos intentaré considerar estas oportunidades y mostrar cómo usarlas.


'diskNumber' => 0, // Por lo general me encontré con 0 en todas partes, y en particular decidí no profundizar en
Como sugirió berez , el número de volumen en el archivo de varios volúmenes.

Source: https://habr.com/ru/post/471066/


All Articles