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

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

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

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


当前回答

这里只提到Django 1.10中提供的FileResponse对象

编辑:在寻找一种简单的通过Django进行文件流处理的方法时,我遇到了自己的答案,所以这里有一个更完整的例子(给未来的我)。它假设FileField名称为imported_file

views.py

from django.views.generic.detail import DetailView   
from django.http import FileResponse
class BaseFileDownloadView(DetailView):
  def get(self, request, *args, **kwargs):
    filename=self.kwargs.get('filename', None)
    if filename is None:
      raise ValueError("Found empty filename")
    some_file = self.model.objects.get(imported_file=filename)
    response = FileResponse(some_file.imported_file, content_type="text/csv")
    # https://docs.djangoproject.com/en/1.11/howto/outputting-csv/#streaming-large-csv-files
    response['Content-Disposition'] = 'attachment; filename="%s"'%filename
    return response

class SomeFileDownloadView(BaseFileDownloadView):
    model = SomeModel

urls . py

...
url(r'^somefile/(?P<filename>[-\w_\\-\\.]+)$', views.SomeFileDownloadView.as_view(), name='somefile-download'),
...

其他回答

上面提到过,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对于较大的文件仍然更好。但如果你不能或不想为此费心,那么这个中间解决方案将为你带来更好的效率,而不会带来麻烦。

def qrcodesave(request): 
    import urllib2;   
    url ="http://chart.apis.google.com/chart?cht=qr&chs=300x300&chl=s&chld=H|0"; 
    opener = urllib2.urlopen(url);  
    content_type = "application/octet-stream"
    response = HttpResponse(opener.read(), content_type=content_type)
    response["Content-Disposition"]= "attachment; filename=aktel.png"
    return response 

使用https://github.com/johnsensible/django-sendfile: https://gist.github.com/iutinvg/9907731提供对静态html文件夹的受保护访问

为了“两全皆美”,你可以将s.l ot的解决方案与xsendfile模块结合起来:django生成文件的路径(或文件本身),但实际的文件服务由Apache/Lighttpd处理。一旦你设置了mod_xsendfile,集成你的视图需要几行代码:

from django.utils.encoding import smart_str

response = HttpResponse(mimetype='application/force-download') # mimetype is replaced by content_type for django 1.7
response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(file_name)
response['X-Sendfile'] = smart_str(path_to_file)
# It's usually a good idea to set the 'Content-Length' header too.
# You can also set any other required headers: Cache-Control, etc.
return response

当然,这只有在你能控制你的服务器,或者你的主机公司已经设置了mod_xsendfile的情况下才会起作用。

编辑:

在django 1.7中,Mimetype被content_type取代

response = HttpResponse(content_type='application/force-download')  

编辑: 对于nginx检查,它使用X-Accel-Redirect而不是apache的X-Sendfile头。