tags:

views:

1694

answers:

3

Is it possible to make a zip archive and offer it to download, but still not save a file to the hard drive?

+4  A: 

Yes, you can use the zipfile module, zlib module or other compression modules to create a zip archive in memory. You can make your view write the zip archive to the HttpResponse object that the Django view returns instead of sending a context to a template. Lastly, you'll need to set the mimetype to the appropriate format to tell the browser to treat the response as a file.

Soviut
+10  A: 

You'll be happier creating a temporary file. This saves a lot of memory. When you have more than one or two users concurrently, you'll find the memory saving is very, very important.

You can, however, write to a StringIO object.

>>> import zipfile
>>> import StringIO
>>> buffer= StringIO.StringIO()
>>> z= zipfile.ZipFile( buffer, "w" )
>>> z.write( "idletest" )
>>> z.close()
>>> len(buffer.getvalue())
778

The "buffer" object is file-like with a 778 byte ZIP archive.

S.Lott
Good point about saving memory. But if using a temporary file, where would you put the code to delete it?
superjoe30
@superjoe30: periodical cleanup jobs. Django already has an admin command that must be run periodically to remove old sessions.
S.Lott
+10  A: 

To trigger a download you need to set Content-Disposition header:

from django.http import HttpResponse
from django.core.servers.basehttp import FileWrapper

# generate the file
response = HttpResponse(FileWrapper(myfile), content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename=myfile.zip'
return response

If you don't want the file on disk you need to use StringIO

import cStringIO as StringIO

myfile = StringIO.StringIO()
while not_finished:
    # generate chunk
    myfile.write(chunk)

Optionally you can set Content-Length header as well:

response['Content-Length'] = myfile.tell()
muhuk
+1 Great I didn't know the Content-Disposition. Thanks :)
luc
I think Content-Length might happen automatically with Django middleware
superjoe30