无法使用 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
字段)。
作为标题,我使用 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
字段)。