我希望网站上的用户能够下载路径被遮蔽的文件,这样他们就不能直接下载。

例如,我希望URL是这样的:http://example.com/download/?f=somefile.txt

在服务器上,我知道所有可下载的文件都位于/home/user/files/文件夹中。

有没有一种方法可以让Django为下载提供这个文件,而不是试图找到一个URL和视图来显示它?


当前回答

你应该在生产环境中使用apache或nginx等流行服务器提供的sendfile api。多年来,我一直在使用这些服务器的sendfile api来保护文件。然后创建了一个简单的基于中间件的django应用程序,适用于开发和生产目的。您可以在这里访问源代码。

更新:在新版本的python提供者使用django FileResponse,如果可用,还增加了对许多服务器实现的支持,从lighthttp, caddy到hiawatha

使用

pip install django-fileprovider

将fileprovider app添加到INSTALLED_APPS设置中 添加fileprovider.middleware.FileProviderMiddleware到MIDDLEWARE_CLASSES设置中 在生产环境中将FILEPROVIDER_NAME设置为nginx或apache,开发时默认为python。

在基于类或函数的视图中,将响应头X-File值设置为文件的绝对路径。例如:

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文件提供程序以一种你的代码只需要最小修改的方式实现。

Nginx配置

要保护文件不被直接访问,可以将配置设置为

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

这里nginx在内部设置了一个url /files/只能访问的位置,如果你使用上述配置,你可以将X-File设置为:

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

通过在nginx配置中这样做,文件将受到保护&你也可以从django视图中控制文件

其他回答

试一试:https://pypi.python.org/pypi/django-sendfile/

“一旦Django检查了权限,抽象的卸载文件上传到web服务器(例如Apache的mod_xsendfile)。”

另一个项目可以看看:http://readthedocs.org/docs/django-private-files/en/latest/usage.html 看起来很有希望,但还没有亲自测试过。

基本上,该项目抽象了mod_xsendfile配置,并允许你做以下事情:

from django.db import models
from django.contrib.auth.models import User
from private_files import PrivateFileField

def is_owner(request, instance):
    return (not request.user.is_anonymous()) and request.user.is_authenticated and
                   instance.owner.pk = request.user.pk

class FileSubmission(models.Model):
    description = models.CharField("description", max_length = 200)
        owner = models.ForeignKey(User)
    uploaded_file = PrivateFileField("file", upload_to = 'uploads', condition = is_owner)

我做过一个关于这个的项目。你可以看看我的github回购:

https://github.com/nishant-boro/django-rest-framework-download-expert

这个模块提供了一种使用Apache模块Xsendfile在django rest框架中下载文件的简单方法。它还有一个额外的功能,即只向属于特定群组的用户提供下载服务

上面提到过,mod_xsendfile方法不允许在文件名中使用非ascii字符。

出于这个原因,我有一个补丁mod_xsendfile,将允许任何文件被发送,只要名称是url编码,和额外的头:

X-SendFile-Encoding: url

也会被发送。

http://ben.timby.com/?p=149

S.Lott有“好的”/简单的解决方案,elo80ka有“最好的”/高效的解决方案。这是一个“更好”/中间的解决方案-没有服务器设置,但更有效的大文件比天真的修复:

http://djangosnippets.org/snippets/365/

基本上,Django仍然处理文件的服务,但不会一次将整个文件加载到内存中。这允许您的服务器(缓慢地)在不增加内存使用的情况下提供大文件。

同样,S.Lott的X-SendFile对于较大的文件仍然更好。但如果你不能或不想为此费心,那么这个中间解决方案将为你带来更好的效率,而不会带来麻烦。