Я не смог найти никаких готовых библиотек, которые поддерживают возобновляемое сжатие так, как мне требовалось.Тем не менее, существует множество фрагментов, доступных по открытым лицензиям, для написания ваших собственных.Теперь у меня есть клиент-серверное решение, которое удовлетворяет всем ограничениям, изложенным в вопросе.
Идея похожа на идеи разбиения на части, изложенные выше, но сервер управляет разбиением на блоки и выполняет некоторую бухгалтерию, которая отображает сжатыечанки на клиенте к сжатым чанкам на сервере.В решении нет временных файлов.Базовый протокол выглядит следующим образом:
(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 (включая сбои на сервере или клиенте) можно безопасно возобновить (хорошо, более или менее).
Есть несколько битов, которые были немного сложными при создании кускового zip-файла.Основная вещь, которая должна быть достигнута, состоит в том, чтобы найти алгоритм сжатия, способный к фрагментам.Таким образом можно использовать Deflate.
java ZipOutputStream и DeflaterOutputStream не очень подходят для дефляции / архивирования по частям, поскольку они не допускают произвольного сброса.Существует лицензионная реализация ZLib в стиле BSD в стиле http://www.jcraft.com/jzlib.. Я не тестировал ее по скорости, но она дает тот же результат, что и реализация Java.JZLib великолепен и поддерживает все режимы очистки ZLib (в отличие от реализации java.util.zip.Deflate).
Кроме того, файлы Zip вычисляют CRC для каждой записи.Таким образом, запись манифеста на шаге 4 содержит «частичный» CRC, который для каждого чанка обновляется и отправляется обратно в информацию бухгалтерского учета на шаге 5. Существует общедоступная реализация CRC для Java на http://www.axlradius.com/freestuff/CRC32.java. Я тестировал его, и он так же быстр (и предоставляет эквивалентные CRC) нативную реализацию Java.
Наконец, формат Zip-файла довольно привередливый.Мне удалось собрать воедино большую часть реализации со страницы википедии и http://www.pkware.com/documents/casestudies/APPNOTE.TXT. Хотя в какой-то момент я не смог найти правильное значение для одного из полей.К счастью, JDK-источник ZipOutputStream доступен, чтобы вы могли видеть, что они делают.