dam*_*mon 231 python django download
我希望网站上的用户能够下载路径被遮挡的文件,因此无法直接下载.
例如,我希望URL是这样的," http://example.com/download/?f=somefile.txt
在服务器上,我知道所有可下载文件都位于"/ home/user/files /"文件夹中.
有没有办法让Django提供该文件供下载,而不是试图找到一个URL和View来显示它?
elo*_*0ka 185
对于"两全其美",您可以将S.Lott的解决方案与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
Run Code Online (Sandbox Code Playgroud)
当然,这只有在您控制服务器或托管公司已设置mod_xsendfile时才有效.
编辑:
对于django 1.7,mimetype被content_type替换
response = HttpResponse(content_type='application/force-download'
Run Code Online (Sandbox Code Playgroud)
编辑:
为了nginx
检查这一点,它使用X-Accel-Redirect
而不是apache
X-Sendfile头.
S.L*_*ott 85
"下载"只是HTTP标头更改.
有关如何通过下载进行回复,请参阅http://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment.
您只需要一个URL定义"/download"
.
请求GET
或POST
字典将包含"f=somefile.txt"
信息.
您的视图函数将简单地将基本路径与" f
"值合并,打开文件,创建并返回响应对象.它应该少于12行代码.
roc*_*eys 27
S.Lott拥有"好"/简单的解决方案,而elo80ka拥有"最佳"/高效的解决方案.这是一个"更好"/中间的解决方案 - 没有服务器设置,但对于大型文件比天真的修复更有效:
http://djangosnippets.org/snippets/365/
基本上,Django仍然处理文件服务,但不会立即将整个内容加载到内存中.这允许您的服务器(缓慢地)提供大文件而不会增加内存使用量.
同样,S.Lott的X-SendFile对于较大的文件仍然更好.但是如果你不能或不想打扰它,那么这个中间解决方案可以让你获得更高的效率而不会有麻烦.
Cor*_*ory 27
对于非常简单但不高效或可扩展的解决方案,您可以使用内置的django serve
视图.这对于快速原型或一次性工作非常有用,但正如在这个问题中提到的那样,你应该在生产中使用类似apache或nginx的东西.
from django.views.static import serve
filepath = '/some/path/to/local/file.txt'
return serve(request, os.path.basename(filepath), os.path.dirname(filepath))
Run Code Online (Sandbox Code Playgroud)
Sal*_*lab 16
试过@Rocketmonkeys解决方案,但下载的文件存储为*.bin并给出随机名称.那当然不好.从@ elo80ka添加另一行解决了这个问题.
这是我现在使用的代码:
from wsgiref.util import FileWrapper
from django.http import HttpResponse
filename = "/home/stackoverflow-addict/private-folder(not-porn)/image.jpg"
wrapper = FileWrapper(file(filename))
response = HttpResponse(wrapper, content_type='text/plain')
response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(filename)
response['Content-Length'] = os.path.getsize(filename)
return response
Run Code Online (Sandbox Code Playgroud)
您现在可以将文件存储在私人目录中(不在/ media或/ public_html内),并通过django将它们暴露给某些用户或在某些情况下.
希望能帮助到你.
感谢@ elo80ka,@ S.Lott和@Rocketmonkeys的答案,得到了完美的解决方案,结合了所有这些=)
sha*_*adi 15
只需提及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
Run Code Online (Sandbox Code Playgroud)
urls.py
...
url(r'^somefile/(?P<filename>[-\w_\\-\\.]+)$', views.SomeFileDownloadView.as_view(), name='somefile-download'),
...
Run Code Online (Sandbox Code Playgroud)
bti*_*mby 13
上面提到mod_xsendfile方法不允许文件名中包含非ASCII字符.
出于这个原因,我有一个可用于mod_xsendfile的补丁,它允许发送任何文件,只要名称是url编码的,以及附加标题:
X-SendFile-Encoding: url
Run Code Online (Sandbox Code Playgroud)
也被送了.
尝试:https://pypi.python.org/pypi/django-sendfile/
"一旦Django检查了权限等,就抽象将文件上传到web服务器(例如带有mod_xsendfile的Apache)"
你应该使用像流行服务器一样apache
或nginx
在生产中给出的sendfile apis .多年来我一直在使用这些服务器的sendfile api来保护文件.然后为此目的创建了一个简单的基于中间件的django应用程序,适用于开发和生产目的.您可以在此处访问源代码.
更新:在新版本python
提供程序中使用django(FileResponse
如果可用)并且还添加了对lighthttp,caddy到hiawatha的许多服务器实现的支持
用法
pip install django-fileprovider
Run Code Online (Sandbox Code Playgroud)
fileprovider
应用添加到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
Run Code Online (Sandbox Code Playgroud)
django-fileprovider
以某种方式强调您的代码只需要最少的修改.
Nginx配置
要保护文件不被直接访问,您可以将配置设置为
location /files/ {
internal;
root /home/sideffect0/secret_files/;
}
Run Code Online (Sandbox Code Playgroud)
这里nginx
设置一个位置url /files/
只访问internaly,如果你使用上面的配置,你可以设置X-File为,
response['X-File'] = '/files/filename.extension'
Run Code Online (Sandbox Code Playgroud)
通过使用nginx配置执行此操作,该文件将受到保护,您还可以从django控制该文件 views
归档时间: |
|
查看次数: |
146318 次 |
最近记录: |