使用Python将多个.CSV文件发送到.ZIP而无需在磁盘中存储

2024-04-29 18:24:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在为我的Django-powered网站开发一个报告应用程序。我想运行几个报表,并让每个报表在内存中生成一个.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文件列表:

^{pr2}$

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


Tags: 文件csvdjango应用程序报表网站responsemy
3条回答

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)

如果您希望将来验证您的代码(hint hint Python 3 hint hint),那么您可能需要切换到使用io.BytesIO而不是StringIO,因为python3是关于字节的。另一个好处是,明确的寻找是不必要的拜特西奥在读取之前(我还没有用Django的HttpResponse测试过这种行为,所以我把最后的搜索放在那里以防万一)。在

^{pr2}$
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)。压缩的默认值是ZIP_STORED,它将创建不压缩的zip文件。在

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.

希望你不会有这个想法。在

相关问题 更多 >