繁体   English   中英

将多个.CSV文件发送到.ZIP而不用Python存储到磁盘

[英]Sending multiple .CSV files to .ZIP without storing to disk in Python

我正在为我的Django网站上的报告应用程序工作。 我想运行多个报告,并让每个报告在内存中生成一个.csv文件,可以批量下载为.zip。 我想这样做而不将任何文件存储到磁盘。 到目前为止,为了生成单个.csv文件,我遵循常见的操作:

mem_file = StringIO.StringIO()
writer = csv.writer(mem_file)
writer.writerow(["My content", my_value])
mem_file.seek(0)
response = HttpResponse(mem_file, content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=my_file.csv'

这很好,但只适用于单个解压缩的.csv。 例如,如果我有一个使用StringIO流创建的.csv文件列表:

firstFile = StringIO.StringIO()
# write some data to the file

secondFile = StringIO.StringIO()
# write some data to the file

thirdFile = StringIO.StringIO()
# write some data to the file

myFiles = [firstFile, secondFile, thirdFile]

我怎样才能返回包含myFiles中所有对象的压缩文件,并且可以正确解压缩以显示三个.csv文件?

zipfile是一个标准的库模块,可以完全满足您的需求。 对于您的用例,肉和土豆是一种称为“writestr”的方法,它采用文件名和包含在其中的您想要压缩的数据。

在下面的代码中,我在解压缩文件时使用了顺序命名方案,但这可以切换到您想要的任何内容。

import zipfile
import StringIO

zipped_file = StringIO.StringIO()
with zipfile.ZipFile(zipped_file, 'w') as zip:
    for i, file in enumerate(files):
        file.seek(0)
        zip.writestr("{}.csv".format(i), file.read())

zipped_file.seek(0)

如果你想对未来的代码进行验证(提示提示Python 3提示提示),你可能想切换到使用io.BytesIO而不是StringIO,因为Python 3完全是关于字节的。 另一个好处是在读取之前io.BytesIO不需要显式搜索(我没有用Django的HttpResponse测试这种行为,所以我在那里留下了最后的搜索以防万一)。

import io
import zipfile

zipped_file = io.BytesIO()
with zipfile.ZipFile(zipped_file, 'w') as f:
    for i, file in enumerate(files):
        f.writestr("{}.csv".format(i), file.getvalue())

zipped_file.seek(0)

stdlib附带模块zipfile ,主类ZipFile接受文件或类文件对象:

from zipfile import ZipFile
temp_file = StringIO.StringIO()
zipped = ZipFile(temp_file, 'w')

# create temp csv_files = [(name1, data1), (name2, data2), ... ]

for name, data in csv_files:
    data.seek(0)
    zipped.writestr(name, data.read())

zipped.close()

temp_file.seek(0)

# etc. etc.

我不是StringIO的用户所以我可能有seekread StringIO的地方,但希望你能得到这个想法。

def zipFiles(files):
    outfile = StringIO() # io.BytesIO() for python 3
    with zipfile.ZipFile(outfile, 'w') as zf:
        for n, f in enumarate(files):
            zf.writestr("{}.csv".format(n), f.getvalue())
    return outfile.getvalue()

zipped_file = zip_files(myfiles)
response = HttpResponse(zipped_file, content_type='application/octet-stream')
response['Content-Disposition'] = 'attachment; filename=my_file.zip'

StringIO有getvalue方法,返回整个内容。 您可以通过zipfile.ZipFile(outfile, 'w', zipfile.ZIP_DEFLATED)压缩zipfile zipfile.ZipFile(outfile, 'w', zipfile.ZIP_DEFLATED) 压缩的默认值是ZIP_STORED ,它将创建压缩文件而不压缩。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM