Send large files through Django, and how to generate Zip files

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import os, tempfile, zipfile
from django.http import HttpResponse
from django.core.servers.basehttp import FileWrapper


def send_file(request):
    """                                                                         
    Send a file through Django without loading the whole file into              
    memory at once. The FileWrapper will turn the file object into an           
    iterator for chunks of 8KB.                                                 
    """
    filename = __file__ # Select your file here.                                
    wrapper = FileWrapper(file(filename))
    response = HttpResponse(wrapper, content_type='text/plain')
    response['Content-Length'] = os.path.getsize(filename)
    return response


def send_zipfile(request):
    """                                                                         
    Create a ZIP file on disk and transmit it in chunks of 8KB,                 
    without loading the whole file into memory. A similar approach can          
    be used for large dynamic PDF files.                                        
    """
    temp = tempfile.TemporaryFile()
    archive = zipfile.ZipFile(temp, 'w', zipfile.ZIP_DEFLATED)
    for index in range(10):
        filename = __file__ # Select your files here.                           
        archive.write(filename, 'file%d.txt' % index)
    archive.close()
    wrapper = FileWrapper(temp)
    response = HttpResponse(wrapper, content_type='application/zip')
    response['Content-Disposition'] = 'attachment; filename=test.zip'
    response['Content-Length'] = temp.tell()
    temp.seek(0)
    return response

More like this

  1. TemplateZipFile by fcurella 1 year, 5 months ago
  2. Upload a zip file with newforms by kylefox 6 years, 2 months ago
  3. Simple file size from bytes to kb/mb/gb by bryanhelmig 3 years, 4 months ago
  4. send_file and send_data by danjak 6 years, 2 months ago
  5. Modified ZipFile() to support writedir() (with auto pyc/py selection) by sleepycal 1 year, 9 months ago

Comments

jdriscoll (on October 9, 2007):

For people on Windows you'll need to specify "read binary" mode for anything other than a text file:

wrapper = FileWrapper(file(filename), "rb")

#

andybak (on August 14, 2008):

As far as I know this is the only way to get password protection for files when you are using Django under FCGI (and I assume CGI and SCGI). For people using mod_python, mod_wsgi there are better solutions.

It would be good to get all this protected or dynamic file download info into one place.

#

hackeron (on May 7, 2009):

Andy, you are saying there are better solutions for people using mod_wsgi? -- Can you list them?

#

hackeron (on May 7, 2009):

Currently this seems to be broken in latest svn? -- I disabled the conditional GET middlewhere and gzip middlewhere and when I pass a FileWrapper to HttpResponse, it returns a page with content-length 0.

#

hackeron (on May 8, 2009):

Not being able to get this working on latest SVN, I've went with this approache instead: http://tn123.ath.cx/mod_xsendfile/ -- this is an apache model but I believe it's built into lighttpd and others. Details of this and other methods available here: http://code.djangoproject.com/ticket/2131

#

kun (on July 19, 2011):

some code in gzip middleware, which like "len(response.content)" will read the FileWrapper, so after that content length is 0.

Maybe edit gzip middleware, then use your own gzip in settings.py

some examples code: https://github.com/akun/dj-download

#

theviaxx (on February 9, 2012):

Got this working with a few tweaks:

wrapper = FileWrapper(open(filename, 'rb'))

#

theviaxx (on February 9, 2012):

and the solution, FixedFileWrapper, at https://code.djangoproject.com/ticket/6027 worked for my purposes

#

hanson2010 (on March 18, 2012):

@theviaxx FixedFileWrapper works for me. Thanks for sharing.

#

(Forgotten your password?)