如何在 PHP 中连接 zip 文件

How to concatenate zip files in PHP

我使用 ZipArchive 构建了一个 zip 文件,其中包含如下目录结构:

analysis_name /
    attachment_file_1.pdf
    attachment_file_2.jpg
    attachment_file_3.jpg
    attachment_file_4.jpg
    attachment_file_5.xlsx

没关系,我可以让用户放心下载。要求是他们需要能够将多个分析放入一个 zip 文件中,这样我们就有这样的东西:

analysis_name_1 /
    attachment_file_1_1.pdf
    attachment_file_1_2.jpg
    ...
analysis_name_2 /
    attachment_file_2_1.pdf
    attachment_file_2_2.jpg
    ...
analysis_name_n /
    attachment_file_3_1.pdf
    attachment_file_3_2.jpg
    ...

我面临的问题是这些合并后的 zip 文件不能超过 16 MB,因为它们必须上传到不同的站点。假设我有 20 个分析,大小从 500 K 到 6 MB 不等。如果我使用 gzip,我很确定我可以制作单独的分析 gzip,贪婪地连接它们直到下一个文件超过 16 MB,然后开始一个新文件。

是否可以使用 zip 文件执行此操作?我不热衷于将 gzip 转换为 zip,因为生成的文件可能会大于 16 MB。

我注意到 this question,和那个作者一样,我正在寻找一个开源解决方案。

我最终做的事情是这样的:

  1. 为每个分析制作一个 zip 文件,将其放在 /tmp 中并确保名称是唯一的。
  2. 将这些临时 zip 文件及其大小放入一个列表中,按大小排序,最大的在前。
  3. 创建一个 "real" zip 文件,并遍历临时文件列表。
  4. 如果 "real" zip 文件的大小加上当前临时 zip 文件的大小小于限制,将进入临时 zip 文件的文件添加到真正的 zip 文件中。如果可以添加文件,请从列表和 /tmp 目录中删除临时 zip 文件。
  5. 如果 "real" zip 文件已满而我们还有临时 zip,请创建一个新的 "real" 文件并返回到第 4 步。

这样就给出了保证小于限制的zip文件列表,并且数量应该是最少的。

有几个注意事项:

  1. 如果您的单次分析超出了限制,您将不得不自己处理。这个算法不行。
  2. 我内部使用的限制比实际限制小 1 MB,因为我不确定 zipped(m) + zipped(n) 的大小是否保证大于 zipped(m + n) .

虽然您可以在 PHP 中实现它,但我最终在 Python 中编写了它,因为由于响应性,它必须在后台进程中完成,并且由于要求用户如有必要,能够多次下载生成的 zip 文件。有点武断,我选择在 Python.

中进行所有后台处理