在Python中将多个.CSV文件发送到.ZIP而不存储到磁盘
我正在为我的Django网站开发一个报告应用程序。我想运行几个报告,并让每个报告在内存中生成一个.csv文件,该文件可以作为.zip文件批量下载。我希望在不将任何文件存储到磁盘的情况下执行此操作。到目前为止,要生成单个.csv文件,我将遵循以下常见操作:在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
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'