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

在Python中将多个.CSV文件发送到.ZIP而不存储到磁盘,python,django,csv,zipfile,Python,Django,Csv,Zipfile,我正在为我的Django网站开发一个报告应用程序。我想运行几个报告,并让每个报告在内存中生成一个.csv文件,该文件可以作为.zip文件批量下载。我希望在不将任何文件存储到磁盘的情况下执行此操作。到目前为止,要生成单个.csv文件,我将遵循以下常见操作: mem_file = StringIO.StringIO() writer = csv.writer(mem_file) writer.writerow(["My content", my_value]) mem_file.seek(0) re

我正在为我的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文件

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
的用户,因此我可能会让
seek
read
不合适,但希望您能理解。

是一个标准的库模块,它完全满足您的需求。对于您的用例,meat and Potations是一个名为“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)
如果您想对代码进行未来验证(提示python3提示),您可能希望切换到使用而不是StringIO,因为python3都是关于字节的。另一个好处是,读取之前io.BytesIO不需要显式搜索(我还没有用Django的HttpResponse测试过这种行为,所以我把最后的搜索留在那里以防万一)

StringIO有
getvalue
方法返回全部内容。您可以压缩zipfile
通过
zipfile.zipfile(outfile'w',zipfile.ZIP_缩小)
。压缩的默认值是
ZIP\u存储的
,它将在不压缩的情况下创建ZIP文件

我建议cStringIO提高性能,因为它完全是用C语言编写的,而不是用Python编写的,已经附带了Python本机库,因此它也应该使用更少的内存开销。完整而全面,感谢您为将来提供BytesIO信息!我想到了这个方法,但出于某种原因,我认为这是不可能的,因为我认为内容类型是将文件标识为.csv的原因。我想用你的方式写扩展就行了。谢谢我还得再等几个小时才能赏金。很高兴能帮上忙!:)@DanLoewenherz你能告诉我什么是“文件”在这里为我,文件在枚举(文件),它包含什么?
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)
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'