Ремонт архива с медицинскими данными
Мой друг столкнулся с очень болезненной житейской проблемой. В ФГБУ «НМИЦ онкологии им. Н.Н. Блохина» Минздрава России ему выдали результаты обследования в битом ZIP-архиве, который в другой больнице распаковать не смогли. В центре тоже помочь не смогли, у ПО медицинского оборудования есть свои глюки, а ничего другого не получить.
После небольшого исследования выяснилось, что архив больше 4 гигабайт, запакован без сжатия и при этом использует 32-битные ZIP-смещения. Это и стало источником проблем. Стандартный ZIP и WinRAR на этом архиве выдавали кучу ошибок: что-то из файлов вынимали, что-то доставали с нулевым размером, что-то вообще отказывались распаковывать.
С помощью Codex сваялся небольшой скрипт, который не пытается использовать стандартную распаковку. Он сам читает служебные структуры ZIP, корректно высчитывает смещения файлов с учетом 32-битной арифметики и переполнения через 4 ГБ, вынимает файлы, проверяет их CRC и делает отчет по результатам.
Симптомы
Если коротко, проблема выглядит так: ZIP-архив больше 4 ГБ не распаковывается обычными средствами. WinRAR, 7-Zip или стандартная библиотека ZIP могут ругаться на CRC, доставать часть файлов с нулевым размером, останавливаться на ошибке или падать с сообщением вроде BadZipFile: Bad magic number for file header.
В моем случае внутри лежали DICOM-файлы медицинского обследования. Такую проблему можно встретить после ПЭТ, ПЭТ/КТ, КТ и других исследований, когда на руки выдают диск или архив с результатами обследования. Но сама проблема не обязательно медицинская. Такой же подход может пригодиться для любого большого ZIP-архива, который записан без сжатия и сломался на 32-битных смещениях.
Что получилось
В итоге удалось достать все данные: 7669 файлов. Из них 7127 прошли CRC-проверку, а первые 542 получили плохой CRC, но при этом имели корректный формат, правильные размеры и выглядели как нормальные DICOM-файлы. Визуально данные были в порядке. Архив перепаковали и передали в больницу для работы.
Про первые 542 файла и их плохой CRC версия только одна: эти файлы были переписаны после создания ZIP-заголовков, но без исправления служебных данных архива. Архив сделан без сжатия, то есть по факту это просто слепленные файлы с разметкой и служебными полями. В такой архив можно перезаписать данные поверх старых, сохранив размеры, и он останется структурно похожим на валидный ZIP. Только CRC в заголовках станет устаревшим.
Видимо, медицинское ПО пишет данные сразу в архив, умеет переписывать их поверх, но начинает сбоить, когда размер переваливает за 4 гигабайта. Центральный каталог архива фактически лежал после отметки 4 ГБ, а в служебных полях остались 32-битные смещения с переполнениями по 4 ГБ.
Универсальный скрипт приложил с небольшим README, если вдруг кому пригодится:
Внутри архива лежит recover_zip_archive.py и короткая инструкция. Скрипт можно запустить в режиме анализа, посмотреть отчет по файлам, а потом распаковать архив в отдельную папку. Он не чинит исходный ZIP на месте, а достает из него данные и пишет манифест с результатами проверки.