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

时间:2013-12-26 22:34:46

标签: python django stream zip

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

从用户视图中,我想以GMail在收到包含多张图片的电子邮件时的方式实现它:它为您提供了一个链接,可以下载包含所有图像的Zip文件,并立即下载。< / p>

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

3 个答案:

答案 0 :(得分:1)

您可以使用https://pypi.python.org/pypi/tubing。这是使用s3的示例,您可以非常轻松地创建rackspace clouldfile Source。创建一个客户编写器(而不是sinks.Objects)来将数据流传输到其他地方,并使用自定义变换器来转换流。

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)

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

Python 3.5 起,就可以创建大型文件/文件夹的zip块流。您可以使用无法搜索的流。因此,现在无需使用ZipStream。 请参阅我的答案here

此处有一个示例:https://repl.it/@IvanErgunov/zipfilegenerator

如果您没有文件路径,但是有很多字节,则可以从示例中排除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模块写入其zipfile自己大小的块。因此,如果您发送一条512字节的流,则仅当zipfile模块决定这样做并且只有其大小时,流才会接收一条数据。它取决于压缩算法,但我认为这不是问题,因为zipfile模块生成小的块<= 16384。