haki
haki

Reputation: 9759

Download a zip file created entirely in memory with Django

I need to generate several csv reports, compress and serve as zip to the user. I'm using this snippet as reference

    ...
    temp = StringIO.StringIO()
    with zipfile.ZipFile(temp,'w') as archive:
        for device in devices:
            csv = Mymodel.get_csv_for(device)
            archive.writestr('{}_device.csv'.format(device), str(csv))

    response = HttpResponse(FileWrapper(temp), content_type='application/zip')
    response['Content-Disposition'] = 'attachment; filename="devices.zip"')

    return response

Looking at the archive.listname() i can see the file names. Looking at temp.getvalue() i can see some string but when I download the file it comes out empty.

Upvotes: 1

Views: 2641

Answers (1)

aumo
aumo

Reputation: 5554

You need to call temp.seek(0) before returning the response, otherwise Python will try to read the memory file from its end (where you left it at after writing the archive to it) and therefore will not find any content and return an empty HTTP response.

You also need to use a StreamingHttpResponse instead of a HttpResponse.

That would give:

...
temp = StringIO.StringIO()
with zipfile.ZipFile(temp,'w') as archive:
    for device in devices:
        csv = Mymodel.get_csv_for(device)
        archive.writestr('{}_device.csv'.format(device), str(csv))

response = StreamingHttpResponse(FileWrapper(temp), content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename="devices.zip"')
response['Content-Length'] = temp.tell()

temp.seek(0)

return response

Upvotes: 3

Related Questions