3

I'm using django-sendfile for sending a large file as attachment to the UI. This works with sendfile.backends.simple backend but when I use sendfile.backends.nginx, it returns 404 error on nginx logs.

I think there was something wrong with my nginx configuration.

views.py

class FileDownloadView(View):
    def get(self, request, id_file):
        obj = FileCombined.objects.get(id_file=id_file)
        return sendfile(request, obj.path, attachment=True)

urls.py

from django.conf.urls import url
from django.urls import path

urlpatterns += [
    path(r'file/id/<str:id_file>/delete/', FileDeleteView.as_view(), name='files-delete'),
    path(r'file/id/<str:id_file>/download/', FileDownloadView.as_view(), name='files-download'),
    ]

settings.py

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
SENDFILE_BACKEND = "sendfile.backends.nginx"
SENDFILE_ROOT = os.path.join(BASE_DIR, 'media')
SENDFILE_URL = '/media'

/etc/nignx/sites-enabled/myapp

server { # simple reverse-proxy
    listen       80;
    server_name  localhost;
    sendfile            on;

    # serve static files
    location /static {
       proxy_pass      http://127.0.0.1:8000/static;
    }

    location /media/ {
        internal;
        root  /home/foo/project/django-combine/media;
    }

    location / {
      proxy_pass      http://127.0.0.1:8000;
    }
}

nginx/access.log

127.0.0.1 - - [30/Dec/2017:08:20:01 +0530] "GET /file/id/5114a7721b6943fb31fc143a20adbec630bb5eb2516d7574b881454209338eed/download/ HTTP/1.1" 404 208 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/52.0.2743.116 Chrome/52.0.2743.116 Safari/537.36"
127.0.0.1 - - [30/Dec/2017:08:25:01 +0530] "GET /file/id/5114a7721b6943fb31fc143a20adbec630bb5eb2516d7574b881454209338eed/download/ HTTP/1.1" 404 208 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/52.0.2743.116 Chrome/52.0.2743.116 Safari/537.36"

Actually the file I want to download was exists inside /home/foo/project/django-combine/media directory.

print(obj.path) exists in my view prints

/home/foo/project/django-combine/media/google-oauth2|817468732648743/33601a74-de02-4b83-8587-1f8c3d8c96fb/output/combined.csv
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
  • It looks like you want to serve your files with URIs starting with `/media/`, yet you're trying to reach URIs starting with `/file/`. Perhaps you could consider correcting the way you generate your files URIs. – vmonteco Dec 30 '17 at 03:17
  • @vmonteco if I make a get request to `/file/id/mmm` url, send-file sends the corresponding file which actually located inside media root directory – Avinash Raj Dec 30 '17 at 03:20
  • If I use the above settings, nginx log returns 404 but my server returns 200 `[30/Dec/2017 03:24:13] "GET /file/id/649a2251ac5c1a5ee4efceb7ee6cf2b6c821471a1b5162e984f97ff357fce703/download/ HTTP/1.0" 200 0` – Avinash Raj Dec 30 '17 at 03:26
  • By "my server" you mean "my WSGI server"? – vmonteco Dec 30 '17 at 03:27
  • yep, wsgi server comes with django which got invoked using `python manage.py runserver` – Avinash Raj Dec 30 '17 at 03:28
  • Could you add your routes? Also the development server should not be used for production. What you use isn't a WSGI server. – vmonteco Dec 30 '17 at 03:30
  • yep the development server should not been used in the production, but i want to test the functionality locally. Do you want me to use any other servers like uwsgi or gunicorn? – Avinash Raj Dec 30 '17 at 03:35
  • @AvinashRaj, I think root should `root /home/foo/project/django-combine/;` and not `root /home/foo/project/django-combine/media/;` – Tarun Lalwani Dec 30 '17 at 07:23
  • @TarunLalwani still it's not working. – Avinash Raj Dec 30 '17 at 09:15
  • @TarunLalwani it works after 1.changing the url like you said, 2. removed `|` from the media file path. Post this as answer. This `|` char gets converted to someother chars which makes impossible for nginx to download that particular file. – Avinash Raj Dec 30 '17 at 10:01

1 Answers1

2

You need to change

root /home/foo/project/django-combine/media/;

to

root /home/foo/project/django-combine/; 

As have /media in root makes the effective path to root /home/foo/project/django-combine/media/media.

You could have even used alias /home/foo/project/django-combine/media/; instead of root /home/foo/project/django-combine/media/. That also would have worked. As for aliases the the location path doesn't get appended

Also you need to make sure you don't have special symbols like | which makes it difficult for nginx to locate the file

Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265