Узел zlib инкрементальный надувать
Я нашел конец local file header
в потоке загрузки большого почтового файла, который
- определяет
deflate
сжатие с - установленный бит 3, указывающий длину сжатых данных, следует за сжатыми данными
и я хотел бы теперь надуть эти данные с помощью Node zlib, но я не могу понять, как передать данные в zlib и получить обратную связь, сообщающую мне, когда поток deflate сам завершился.
Поддерживает ли библиотека zlib в Node потребление кусков дефлированных данных и возвращает результат, сообщая вызывающей стороне о завершении потока дефляции?
Или это безумная вещь, потому что это означает, что я надуваю поток пользовательского интерфейса, и что я действительно должен сделать, это сохранить загруженный файл и после загрузки использовать пакет NPM? Хм.. ну.. либо сеть быстрее инфляции, в этом случае потоковая инфляция замедлит работу сети (облом), либо сеть медленнее потоковой инфляции, так зачем делать дефляцию во время потоковой передачи (что я не могу понять, как это сделать в любом случае)), когда я мог просто сохранить на диск и перезагрузить-выкачать, пока я сижу в ожидании сети..
Тем не менее, для моего назидания, я все еще хотел бы знать, поддерживает ли Node потоковую инфляцию.
var zlib = require('zlib')
var data = bufferOfChunkOfDeflatedData
var inflate = zlib.createInflate();
var stream = inflate.pipe(fs.createWriteStream(path));
var result = stream.write(data);
// but result doesn't indicate if the inflate stream has terminated...
Описывает заголовки deflate и как они кодируют длину потока: https://www.bolet.org/~pornin/deflate-flush-fr.html
В потоке памяти: https://www.npmjs.com/package/memory-streams
Ну, этот парень просто тянет, пока не достигнет волшебной подписи!:) https://github.com/EvanOxfeld/node-unzip/blob/5a62ecbcef6523708bb8b37decaf6e41728ac7fc/lib/parse.js#L152
Код узла для настройки вспомогательного метода: https://github.com/nodejs/node/blob/6e56771f2a9707ddf769358a4338224296a6b5fe/lib/zlib.js#L83 Конкретно: https://nodejs.org/api/zlib.html
Эх, похоже, узел настроен так, чтобы возвращать распакованный буфер как один блок для обратного вызова; Не похоже, что узел настроен для определения конца потока дефляции.
https://nodejs.org/api/stream.html#stream_transform_transform_chunk_encoding_callback говорит The callback function must be called only when the current chunk is completely consumed.
и вот место, где он передает кусок в zlib https://github.com/nodejs/node/blob/6e56771f2a9707ddf769358a4338224296a6b5fe/lib/zlib.js#L358. Таким образом, нет возможности сказать, что поток был частично потреблен..
Но опять же... https://github.com/ZJONSSON/node-unzipper/blob/affbf89b54b121e85dcd31adf7b1dfde58afebb7/lib/parse.js#L161 но не совсем. Также просто проверяет наличие магического сигнала: https://github.com/ZJONSSON/node-unzipper/blob/affbf89b54b121e85dcd31adf7b1dfde58afebb7/lib/parse.js#L153
И из спецификации почтового индекса:
4.3.9.3 Хотя изначально подпись не назначена, значение 0x08074b50 обычно принимается как значение подписи для записи дескриптора данных. Разработчики ДОЛЖНЫ знать, что ZIP-файлы МОГУТ встречаться с дескрипторами данных маркировки подписи или без них, и ДОЛЖНЫ учитывать любой случай при чтении ZIP-файлов для обеспечения совместимости.
Похоже, что все просто ищут сигнал.
Марк говорит, что нет-нет... Так что не делай этого. И знайте, что если вы используете библиотеку NPM для распаковки, то есть большая вероятность, что библиотека делает это. Чтобы сделать это правильно, я думаю, что это нужно сделать из документации по API zlib: https://zlib.net/manual.html
Опция Z_BLOCK помогает добавлять или объединять потоки выкачивания. Чтобы помочь в этом, при возврате inflate() всегда устанавливает strm->data_type в число неиспользованных битов в последнем байте, взятом из strm->next_in, плюс 64, если inflate() в настоящее время декодирует последний блок в потоке deflate, плюс 128, если inflate() возвращается сразу после декодирования кода конца блока или декодирования полного заголовка вплоть до первого байта потока deflate. Конец блока не будет указан, пока все несжатые данные из этого блока не будут записаны в strm->next_out. Количество неиспользуемых битов в общем случае может быть больше семи, за исключением случая, когда установлен бит 7 типа data_type, и в этом случае количество неиспользуемых битов будет меньше восьми. Тип data_type устанавливается, как указано здесь, каждый раз, когда inflate() возвращает все параметры сброса, и поэтому может использоваться для определения количества потребляемого в настоящее время ввода в битах.
Кажется, это указывает на то, что последний сжатый бит не будет выровнен по байту. Тем не менее, спецификация ZIP, по-видимому, указывает, что заголовок, начинающийся с волшебного знака, тот, который каждый использует, но не должен, выровнен по байту: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
4.3.9.1 Этот дескриптор ДОЛЖЕН существовать, если установлен бит 3 флага бит общего назначения (см. Ниже). Он выровнен по байту и сразу следует за последним байтом сжатых данных. Этот дескриптор ДОЛЖЕН использоваться только в том случае, если поиск выходного файла.ZIP невозможен, например, когда выходной файл.ZIP был стандартным выходным устройством или устройством без возможности поиска. Для архивов формата ZIP64(tm) сжатый и несжатый размеры составляют 8 байт каждый.
Как конец потока deflate не может быть выровнен по байту, но следующий дескриптор данных может быть выровнен по байту?
Есть хорошая справочная реализация?
Ссылка подразумевает использование Inflate с Z_BLOCK: https://github.com/madler/zlib/blob/master/examples/gzappend.c
Этот парень читает в обратном направлении, чтобы вытащить каталог: https://github.com/antelle/node-stream-zip/blob/907c8876e8aeed6c33a668bbd06a0f79e7a022ef/node_stream_zip.js#L180 Это необходимо?
Этот парень, кажется, думает, что почтовые индексы нельзя надувать, не прочитав весь файл, чтобы попасть в каталог: https://www.npmjs.com/package/yauzl
Я не понимаю, почему это так. Потоки описывают их длину... и Марк проверяет, что они могут быть переданы в поток.
И вот где Node.js проверяет Z_STREAM_END
!
1 ответ
Похоже, что это так, поскольку списки документации zlib.constants.Z_STREAM_END
в качестве возможного возвращаемого значения.