- Author:
- jcrocholl
- Posted:
- August 12, 2007
- Language:
- Python
- Version:
- .96
- Score:
- 11 (after 11 ratings)
This snippet demonstrates how you can send a file (or file-like object) through Django without having to load the whole thing into memory. The FileWrapper will turn the file-like object into an iterator for chunks of 8KB.
This is a full working example. Start a new app, save this snippet as views.py, and add the views to your URLconf. The send_file view will serve the source code of this file as a plaintext document, and the send_zipfile view will generate a Zip file with 10 copies of it.
Use this solution for dynamic content only, or if you need password protection with Django's user accounts. Remember that you should serve static files directly through your web server, not through Django:
http://www.djangoproject.com/documentation/modpython/#serving-media-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
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
For people on Windows you'll need to specify "read binary" mode for anything other than a text file:
#
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.
#
Andy, you are saying there are better solutions for people using mod_wsgi? -- Can you list them?
#
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.
#
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
#
Got this working with a few tweaks:
#
and the solution, FixedFileWrapper, at https://code.djangoproject.com/ticket/6027 worked for my purposes
#
@theviaxx
FixedFileWrapper
works for me. Thanks for sharing.#
Please login first before commenting.