无法使用 SSZipArchive 在 iOS9 中解压缩大型 zip 文件 (3.3GB)

Unable to unzip a large zip file (3.3GB) in iOS9 using SSZipArchive

作为标题,我使用 python zipfile 模块从我的 Django 后端服务器(托管在 Ubuntu 14.04.1 LTS 上)创建了 zip 文件:

zipfile.ZipFile(dest_path, mode='w', compression=zipfile.ZIP_DEFLATED, 
                allowZip64=True)

我设法在 Finder 中使用 Mac 打开它,但使用 SSZipArchive 库没有成功。我尝试使用 master 分支的最新提交并标记 v1.0.1 和 v0.4.0.

使用 v0.4.0,我在 unzip.c 的第 1506 行出错:

    if (unz64local_CheckCurrentFileCoherencyHeader(s,
                                                   &iSizeVar, 
                                                   &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
        return UNZ_BADZIPFILE;

并且每次解压缩时都卡在同一个文件上 currentFileNumber

有人得到任何线索吗?

P.S。我认为 SSZipArchive 应该支持 Zip64 存档文件,因为我在他们的 github 仓库中询问了 question

更新 [20160129] 我对 zip 文件执行了 zipinfo 检查并得到以下输出:

...
-rw-r--r--  2.0 unx     1992 b- defN 26-Nov-15 14:59 <file_name>
-rw-r--r--  2.0 unx      925 b- defN 26-Nov-15 14:59 <file_name>
-rw-r--r--  2.0 unx     1194 b- defN 26-Nov-15 14:59 <file_name>
-rw-r--r--  2.0 unx       72 b- defN 26-Nov-15 14:52 <file_name>
-rw-r--r--  2.0 unx      289 b- defN 18-Jan-16 11:27 <file_name>
-rw-r--r--  2.0 unx     1541 b- defN 18-Jan-16 11:27 <file_name>
-rw-r--r--  2.0 unx      295 b- defN 18-Jan-16 11:27 <file_name>
-rw-r--r--  2.0 unx 449619181 b- defN 18-Jan-16 11:26 <file_name>
-rw-r--r--  4.5 unx 73128184 bx defN 18-Jan-16 11:26 <file_name>
-rw-r--r--  4.5 unx 69444488 bx defN 18-Jan-16 11:26 <file_name>
-rw-r--r--  4.5 unx   671440 bx defN 18-Jan-16 11:26 <file_name>
-rw-r--r--  4.5 unx 20189549 bx defN 18-Jan-16 11:27 <file_name>
-rw-r--r--  4.5 unx      197 bx defN 18-Jan-16 11:26 <file_name>
-rw-r--r--  4.5 unx  1379396 bx defN 18-Jan-16 11:26 <file_name>
...

经过十几次试错,发现是pythonzipfile包生成的zip文件有问题。如果我使用版本

的Ubuntu服务器提供的zip命令

Copyright (c) 1990-2008 Info-ZIP - Type 'zip "-L"' for software license.

This is Zip 3.0 (July 5th 2008), by Info-ZIP.

要归档4GB的大数据,SSZipArchive可以成功解压zip包。

我用 zipinfo 测试了 zip 文件,发现:

...
-rw-r--r--  3.0 unx     2939 bx     2677 defN 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx    15069 bx     3040 defN 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx     3265 bx     3003 defN 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx     3048 bx     2766 defN 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx     3453 bx     3168 defN 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx     1415 tx      534 defN 16-Jan-28 16:33 <file_name>
drwxr-xr-x  3.0 unx        0 bx        0 stor 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx     3302 tx      695 defN 16-Jan-28 16:33 <file_name>
drwxr-xr-x  3.0 unx        0 bx        0 stor 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx   130678 bx   127322 defN 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx   133540 bx   130045 defN 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx      136 tx       71 defN 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx     1416 tx      541 defN 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx     1417 tx      541 defN 16-Jan-28 16:33 <file_name>
-rw-r--r--  3.0 unx     2766 tx      652 defN 16-Jan-28 16:33 <file_name>
5551 files, 3854751563 bytes uncompressed, 3793408959 bytes compressed:  1.6%

总结上面提到但没有强调的东西: 问题是由 ZIP header 版本字段引起的——该字段在存档中每个文件的 header 中重复出现。 默认 Linux zip 命令 (Info-ZIP) 使用 header 版本 3.0,如上面的答案所示。 Python 默认使用 header 2.0。但是,如果某些文件超过 2GB 大小阈值,则 Python 会为此文件和后续文件切换到 4.5 header 版本。看起来这会导致 SSZipArchive.

出现问题

我目前的临时解决方法是 monkey-patch zipfile 模块:

import zipfile
zipfile.ZIP64_VERSION = 30  # instead of 45

这将创建 SSZipArchive 可读的 zip 存档,但我认为它也将违反 Zip64 standard,其中规定 For Zip64 format archives, this value should not be less than 45(对于 extract_version 字段)。