节点zlib增量膨胀

时间:2019-02-26 04:15:41

标签: node.js zip zlib zipfile nodejs-stream

我在大型zip文件的下载流中找到了local file header的结尾

  • 使用
  • 指定deflate压缩
  • 第3位设置指示压缩数据的长度紧随压缩数据之后

,现在想使用Node zlib对该数据进行充气,但是我无法弄清楚如何将数据馈入zlib并接收反馈,该信息告诉我deflate流何时自行终止。

Node的zlib库是否支持消耗大量的deflate数据并返回结果,以使调用者知道deflate流何时结束?

这是否是一件疯狂的事情,因为这将暗示我正在夸大UI线程,而我真正应该做的就是保存下载的文件,并在下载后使用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#zlib_zlib_inflateraw_buffer_options_callback


嗯,看起来好像已经设置了节点,以将解压缩的缓冲区作为一个块返回给回调;看起来好像没有设置node来确定deflate流的末尾。

https://nodejs.org/api/stream.html#stream_transform_transform_chunk_encoding_callbackThe 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


根据zip规范:

  

4.3.9.3尽管最初未分配签名,但该值         通常将0x08074b50用作签名值         用于数据描述符记录。实施者应该         注意有或没有此文件都可能会遇到ZIP文件         签名标记数据描述符和应该用于         读取ZIP文件以确保兼容性时,这两种情况都是如此。

所以看起来每个人都只是在寻找信号。


马克说那是不行...所以不要那样做。并且知道,如果您使用NPM库解压缩,那么该库很有可能会这样做。我认为,要正确执行此操作,需要从zlib API文档中获取:https://zlib.net/manual.html

  

Z_BLOCK选项有助于附加或组合放气流。为了解决这个问题,在返回时,inflate()始终将strm-> data_type设置为从strm-> next_in获取的最后一个字节中未使用的位数,如果inflate()当前正在解码deflate流中的最后一个块,则将其设置为64,如果在解码完块结束代码或解码完整的标头之后紧接着在deflate流的第一个字节之前返回inflate(),则返回128。在该块的所有未压缩数据都已写入strm-> next_out之前,不会指示该块的末尾。除了设置data_type的位7时,未使用的位数通常可以大于七个,在这种情况下,未使用的位数将小于八个。每次为所有刷新选项返回inflate()时,都会按此处所述设置data_type,因此可用于确定当前消耗的输入量(以位为单位)。

这似乎表明最终的压缩位将不按字节对齐。但是ZIP规范似乎表明标头以魔术sig开头,每个人都在使用但不应该这样,标头是按字节对齐的: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#no-streaming-unzip-api

,就无法压缩zip。

我不知道为什么会这样。流描述了它们的长度...并且Mark验证了它们是否可以流化。


here是Node.js检查Z_STREAM_END的地方!

1 个答案:

答案 0 :(得分:0)

看起来像这样,因为文档列出了zlib.constants.Z_STREAM_END作为可能的返回值。