Having Django serve downloadable files

2018-12-31 08:19发布

I want users on the site to be able to download files whose paths are obscured so they cannot be directly downloaded.

For instance, I'd like the URL to be something like this, "http://example.com/download/?f=somefile.txt

And on the server, I know that all downloadable files reside in a folder "/home/user/files/".

Is there a way to make Django serve that file for download as opposed to trying to find a URL and View to display it?

14条回答
琉璃瓶的回忆
2楼-- · 2018-12-31 09:05

I have faced the same problem more then once and so implemented using xsendfile module and auth view decorators the django-filelibrary. Feel free to use it as inspiration for your own solution.

https://github.com/danielsokolowski/django-filelibrary

查看更多
栀子花@的思念
3楼-- · 2018-12-31 09:07

You should use sendfile apis given by popular servers like apache or nginx in production. Many years i was using sendfile api of these servers for protecting files. Then created a simple middleware based django app for this purpose suitable for both development & production purpose.You can access the source code here.
UPDATE: in new version python provider uses django FileResponse if available and also adds support for many server implementations from lighthttp, caddy to hiawatha

Usage

pip install django-fileprovider
  • add fileprovider app to INSTALLED_APPS settings,
  • add fileprovider.middleware.FileProviderMiddleware to MIDDLEWARE_CLASSES settings
  • set FILEPROVIDER_NAME settings to nginx or apache in production, by default it is python for development purpose.

in your classbased or function views set response header X-File value to absolute path to the file. For example,

def hello(request):  
   // code to check or protect the file from unauthorized access
   response = HttpResponse()  
   response['X-File'] = '/absolute/path/to/file'  
   return response  

django-fileprovider impemented in a way that your code will need only minimum modification.

Nginx configuration

To protect file from direct access you can set the configuration as

 location /files/ {
  internal;
  root   /home/sideffect0/secret_files/;
 }

Here nginx sets a location url /files/ only access internaly, if you are using above configuration you can set X-File as,

response['X-File'] = '/files/filename.extension' 

By doing this with nginx configuration, the file will be protected & also you can control the file from django views

查看更多
登录 后发表回答