我找不到任何以我需要的方式支持可恢复压缩的预制造库。然而,许多公开许可证可用于编写自己的零件。我现在有了一个客户/服务器解决方案,可以满足问题中列出的所有限制。
这个想法类似于上面概述的组块想法,但服务器管理分块并做一些簿记,将客户端上的压缩块映射到服务器上的压缩块。解决方案中没有任何临时文件。基本方案如下
(1) The client sends a manifest to the server, containing the
to-be contents of the zip file
(2) The server sends back an ID for the manifest
Then repeatedly
(3) The client asks the server "is there anything still
required for the manifest with ID X"
(4) The server replies "no", or with a manifest entry
for a file in the manifest, plus a offset and length to send
(5) The client compresses that chunk and sends it (plus some
bookkeeping info)
(6) The server puts the chunk into the every growing zip file,
plus appropriate zip file crud. If the server orders
the chunks it asks the client for appropriately, this can
all be done by file appends.
服务器仅更新清单每个时间步6成功完成,所以在步骤3-6(包括服务器或客户端上崩溃)的故障可以被安全地(当然,更恢复或更少)。
在做块文件压缩文件创建时有一些小小的错误。需要实现的基本原则是找到一个可分块的压缩算法。 Deflate可以用这种方式使用。
java ZipOutputStream和DeflaterOutputStream并不真正适用于'明智的'放气/压缩,因为它们不允许任意刷新。在http://www.jcraft.com/jzlib有一个BSD风格的许可java实现ZLib。我没有对速度进行基准测试,但它提供了与Java实现相同的输出。 JZLib很棒,支持ZLib的所有刷新模式(与java.util.zip.Deflate实现不同)。
此外,Zip文件计算每个条目的CRC。因此,步骤4中的清单条目包含一个“部分”CRC,对每个块进行更新并在步骤5的簿记信息中将其发送回去。在http://www.axlradius.com/freestuff/CRC32.java处有一个针对java的CRC的公共域实现。我已经对它进行了基准测试,它和本地java实现一样快(并提供了等效的CRC)。
最后,Zip文件格式非常不合适。我设法将wikipedia页面和http://www.pkware.com/documents/casestudies/APPNOTE.TXT的大部分实现拼凑在一起。尽管在某一点上,我无法为其中一个领域提供正确的价值。幸运的是,JDK的ZipOutputStream源是可用的,所以你可以看到他们做了什么。
有几个人建议分块。除了上面的条件(2),这是一个好主意。如果我大块,我没有办法(我知道)从大块制作一个有效的.zip/.gz文件。 – 2010-07-28 03:56:44
就像我说的,你需要在客户端存储一个文件或者在服务器上重新组装。唯一的选择是有效地将整个文件加载到内存中,然后在客户端上创建文件的内存中版本。 – cletus 2010-07-28 04:03:11