0

我找到了local file header一个大型 zip 文件的下载流的末尾

  • 指定deflate压缩与
  • 位 3 设置指示压缩数据的长度跟随压缩数据

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

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...

描述放气标头以及它们如何编码流的长度: 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


呃,看起来节点设置为将解压缩的缓冲区作为一个块返回给回调;看起来节点没有设置为找出放气流的结尾。

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,加上 128 如果 inflate() 在解码块结束代码或解码完整标头后立即返回,直到放气流的第一个字节之前。在该块中的所有未压缩数据都已写入 strm->next_out 之前,不会指示块结束。未使用的位数通常可以大于 7,除非 data_type 的第 7 位被设置,在这种情况下未使用的位数将小于 8。每次 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 的参考 impl:https ://github.com/madler/zlib/blob/master/examples/gzappend.c


这家伙向后阅读以拉出目录:https ://github.com/antelle/node-stream-zip/blob/907c8876e8aeed6c33a668bbd06a0f79e7a022ef/node_stream_zip.js#L180这有必要吗?

这家伙似乎认为,如果不阅读整个文件以进入目录,则无法膨胀 zip:https ://www.npmjs.com/package/yauzl#no-streaming-unzip-api

我不明白为什么会这样。流描述了它们的长度……Mark 验证它们可以流化。


这是 Node.js 检查的地方Z_STREAM_END

4

1 回答 1

0

看起来确实如此,因为文档列出zlib.constants.Z_STREAM_END了可能的返回值。

于 2019-02-26T07:04:40.493 回答