views:

220

answers:

2

I am avoiding the creation of files on disk, this is what I have got so far:

def get_zip(request):
    import zipfile, StringIO
    i = open('picture.jpg', 'rb').read()
    o = StringIO.StringIO()
    zf = zipfile.ZipFile(o, mode='w')
    zf.writestr('picture.jpg', i)
    zf.close()
    o.seek(0)
    response = HttpResponse(o.read())
    o.close()
    response['Content-Type'] = 'application/octet-stream'
    response['Content-Disposition'] = "attachment; filename=\"picture.zip\""
    return response

Do you think is correct-elegant-pythonic enough? Any better way to do it?

Thanks!

+2  A: 

Avoiding disk files can slow your server to a crawl, but it will certainly work.

You'll exhaust memory if you serve too many of these requests concurrently.

S.Lott
@S.Lott, I'm curious, is the only concern here exhausting memory? I would think avoiding writing tmp files to disk would be faster. Thanks.
Mark
Temporary files don't necessarily have to hit the disk (especially on Linux).
Lukáš Lalinský
@Mark: You don't know until you measure. However, in general, web servers are (1) socket I/O bound and then (2) memory-bound if there is enough socket bandwidth. Disk I/O is rarely a consideration; the client browser is usually the slowest thing; a large memory transaction ties up large piles of memory waiting for the client browser to finish accepting the stream. Bad policy.
S.Lott
Very interesting, thanks!
Mark
@S.Lott Okay, so in your opinion it would be better to create a zip file, add 'picture.zip' to it, read the resulting zip contents into memory and delete the temp zip file before finally returning the zip contents in the HTTP response?
nabucosound
@nabucosound: If you have the whole JPG or whole ZIP file in memory, you're not doing the right thing. First, don't read the whole JPEG, just give the name to ziplib. Second, don't read the whole ZIP file; merely read 4K at a time and "stream" the bytes in small chunks.
S.Lott
+5  A: 

For StringIO you should generally use o.getvalue() to get the result. Also, if you want to add a normal file to the zip file, you can use zf.write('picture.jpg'). You don't need to manually read it.

Lukáš Lalinský