我希望网站上的用户能够下载路径被遮蔽的文件,这样他们就不能直接下载。
例如,我希望URL是这样的:http://example.com/download/?f=somefile.txt
在服务器上,我知道所有可下载的文件都位于/home/user/files/文件夹中。
有没有一种方法可以让Django为下载提供这个文件,而不是试图找到一个URL和视图来显示它?
我希望网站上的用户能够下载路径被遮蔽的文件,这样他们就不能直接下载。
例如,我希望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'),
...
其他回答
这里只提到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'),
...
我做过一个关于这个的项目。你可以看看我的github回购:
https://github.com/nishant-boro/django-rest-framework-download-expert
这个模块提供了一种使用Apache模块Xsendfile在django rest框架中下载文件的简单方法。它还有一个额外的功能,即只向属于特定群组的用户提供下载服务
“下载”只是一个HTTP报头更改。
请参阅http://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment了解如何回复下载。
“/download”只需要一个URL定义。
请求的GET或POST字典将有“f=somefile.txt”信息。
您的视图函数将简单地合并基本路径与“f”值,打开文件,创建并返回一个响应对象。它应该少于12行代码。
Django建议您使用另一台服务器来提供静态媒体(在同一台机器上运行另一台服务器是可以的)。他们建议使用lighttp这样的服务器。
设置起来非常简单。然而。如果'somefile.txt'是在请求时生成的(内容是动态的),那么你可能想让django来服务它。
Django Docs -静态文件
为了“两全皆美”,你可以将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头。