[英]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
的用户所以我可能有seek
和read
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.