Serve protected media files with django Serve protected media files with django nginx nginx

Serve protected media files with django


I now came up with the following solution:

I have this in my Django settings:

MEDIA_ROOT = "/projects/project/media/"MEDIA_URL = "/media/

In my models I do either:

document = models.FileField(upload_to="public/documents")

or

document = models.FileField(upload_to="protected/documents")

This way, I now have the two subdirectories 'public' and 'protected' in my media files directory.

Nginx or Djangos development server only serves the files in the 'public' subdirectory.

For Djangos development server:

if os.environ["ENVIRONMENT_TYPE"] == 'development':    urlpatterns += static(settings.MEDIA_URL + "public/", document_root=settings.MEDIA_ROOT + "public/")

And for Nginx (used in production):

location /media/public/ {    alias   /projects/project/media/public/;}

When I want to serve a protected document, I do the following:

In urls.py:

url(r'^media/protected/documents/(?P<file>.*)$', core.views.serve_protected_document, name='serve_protected_document'),

And in views.py:

@login_required()def serve_protected_document(request, file):    document = get_object_or_404(ProtectedDocument, file="protected/documents/" + file)    # Split the elements of the path    path, file_name = os.path.split(file)    response = FileResponse(document.file,)    response["Content-Disposition"] = "attachment; filename=" + file_name    return response

I would appreciate any comments! Are there better ways to implement this?


Serving media files ( that may be large files) from view directly is not good. You can use sendfile extension available in nginx server; a sample nginx configuration is like below.

 location /projects/project/media/{    # this path is not public    internal;    # absolute path    alias /projects/project/media/; }

change your view to

@login_requireddef serve_protected_document(request, file):    document = get_object_or_404(ProtectedDocument, file="protected/documents/" + file)    # Split the elements of the path    path, file_name = os.path.split(file)    response = HttpResponse()    response["Content-Disposition"] = "attachment; filename=" + file_name    # nginx uses this path to serve the file    response["X-Accel-Redirect"] = document.name # path to file    return response

Link: More details on configuring sendfile extension on nginx is here