如何从一组流生成 Zip 并使用 Zip 数据生成流

  • 本文关键字:Zip 数据 一组 python django stream zip
  • 更新时间 :
  • 英文 :


我有一个管理一组文件的应用程序,但这些文件实际上存储在Rackspace的CloudFiles中,因为大多数文件将是~100GB。我正在使用Cloudfile的TempURL功能来允许单个文件,但有时,用户会想要下载一组文件。但是下载所有这些文件并生成本地 Zip 文件是不可能的,因为服务器只有 40GB 的磁盘空间。

从用户的角度来看,当您收到包含几张图片的电子邮件时,我想像 GMail 那样实现它:它为您提供了一个链接来下载包含所有图像的 Zip 文件,并且下载是即时的。

如何使用Python/Django实现这一点?我发现了 ZipStream,并且由于迭代器输出而看起来很有前途,但它仍然只接受文件路径作为参数,并且 writestr 方法需要一次获取所有文件数据(~100GB)。

Python 3.5开始,可以创建大文件/文件夹的zip块流。您可以使用不可搜索的流。所以现在不需要使用ZipStream。在这里看到我的答案。

在这里活生生的例子:https://repl.it/@IvanErgunov/zipfilegenerator

如果您没有 filepath,但有字节块,则可以从示例中排除open(path, 'rb') as entry,并将iter(lambda: entry.read(16384), b'')替换为可迭代的字节。并手动准备 ZipInfo:

zinfo = ZipInfo(filename='any-name-of-your-non-existent-file', date_time=time.localtime(time.time())[:6])
zinfo.compress_type = zipfile.ZIP_STORED
# permissions:
if zinfo.filename[-1] == '/':
   # directory
   zinfo.external_attr = 0o40775 << 16   # drwxrwxr-x
   zinfo.external_attr |= 0x10           # MS-DOS directory flag
else:
   # file
   zinfo.external_attr = 0o600 << 16     # ?rw-------

您还应该记住,zipfile 模块会写入其 zip 文件自身大小的块。因此,如果您发送一段 512 字节,则流只有在 zipfile 模块决定这样做时才会收到一段数据。这取决于压缩算法,但我认为这不是问题,因为 zipfile 模块会制作小块 <= 16384。

您可以使用 https://pypi.python.org/pypi/tubing。下面是一个使用 s3 的示例,您可以非常轻松地创建一个机架空间 clouldfile Source。创建客户编写器(而不是接收器。对象)将数据流式传输到其他位置,并自定义转换器来转换流。

from tubing.ext import s3
from tubing import pipes, sinks
output = s3.S3Source(bucket, key) 
    | pipes.Gunzip() 
    | pipes.Split(on=b'n') 
    | sinks.Objects()
print len(output)

看看这个 - 它是 Python 标准库的一部分:http://docs.python.org/3/library/zipfile.html#zipfile-objects

您可以为其提供打开的文件或类似文件的对象。

相关内容

  • 没有找到相关文章

最新更新