import posixpath
import urllib
import os
from django.conf import settings
from django.views.static import serve
from django.http import HttpResponse
USE_XSENDFILE = getattr(settings, 'USE_XSENDFILE', False)
def xsendfileserve(request, path, document_root=None):
"""
Serve static files using X-Sendfile below a given point
in the directory structure.
This is a thin wrapper around Django's built-in django.views.static,
which optionally uses USE_XSENDFILE to tell webservers to send the
file to the client. This can, for example, be used to enable Django's
authentication for static files.
To use, put a URL pattern such as::
(r'^(?P<path>.*)$', login_required(xsendfileserve),
{'document_root' : '/path/to/my/files/'})
in your URLconf. You must provide the ``document_root`` param. You may
also set ``show_indexes`` to ``True`` if you'd like to serve a basic index
of the directory. This index view will use the template hardcoded below,
but if you'd like to override it, you can create a template called
``static/directory_index.html``.
"""
if USE_XSENDFILE:
# This code comes straight from the static file serve
# code in Django 1.2.
# Clean up given path to only allow serving files below document_root.
path = posixpath.normpath(urllib.unquote(path))
path = path.lstrip('/')
newpath = ''
for part in path.split('/'):
if not part:
# Strip empty path components.
continue
drive, part = os.path.splitdrive(part)
head, part = os.path.split(part)
if part in (os.curdir, os.pardir):
# Strip '.' and '..' in path.
continue
newpath = os.path.join(newpath, part).replace('\\', '/')
if newpath and path != newpath:
return HttpResponseRedirect(newpath)
fullpath = os.path.join(document_root, newpath)
# This is where the magic takes place.
response = HttpResponse()
response['X-Sendfile'] = fullpath
# Unset the Content-Type as to allow for the webserver
# to determine it.
response['Content-Type'] = ''
return response
return serve(request, path, document_root)
Comments
Is there anyway to change the default name of the saved file? Currently, it's being saved as 'download'. I've tried:
response['Content-Disposition'] = 'attachment; filename=AnotherName'
but that doesn't help.
Any ideas?
#