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

Jam*_*ell 8 python csv django zipfile

我正在为我的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'
Run Code Online (Sandbox Code Playgroud)

这很好,但只适用于单个解压缩的.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]
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*erz 13

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)
Run Code Online (Sandbox Code Playgroud)

如果你想对未来的代码进行验证(暗示提示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)
Run Code Online (Sandbox Code Playgroud)

  • 完整而全面,感谢您为将来包含BytesIO信息!这种方法在我脑海中浮现,但由于某种原因我不认为这是可能的,因为我虽然content_type是将文件识别为.csv.我想以你的方式编写扩展就可以了.谢谢!我还要等几个小时来奖励赏金. (2认同)