在Django中提供大文件(高负载)

30 python django permissions download

我一直在使用一种方法来提供下载,但由于它不安全,我决定改变它.(该方法是存储中原始文件的链接,但风险是每个有链接的人都可以下载文件!)所以我现在通过我的视图提供文件,这样只有有权限的用户才能下载文件,但我注意到服务器上的负载很高,而文件同时有很多下载请求.这是我处理用户下载的代码的一部分(考虑文件是图像)

    image = Image.open ("the path to file")
    response = HttpResponse(mimetype = 'image/png' )
    response['Content-Disposition'] = 'attachment: filename=%s.png' % filename
    image.save(response , "png")
    return response  
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来提供文件,同时保持安全性和降低服务器端负载?提前致谢 :)

Bur*_*lid 57

您打开图像会将其加载到内存中,这是导致大量使用时负载增加的原因.由Martin发布,真正的解决方案是直接提供文件.

这是另一种方法,它将以块的形式传输文件而不将其加载到内存中.

import os
import mimetypes
from django.http import StreamingHttpResponse
from django.core.servers.basehttp import FileWrapper


def download_file(request):
   the_file = '/some/file/name.png'
   filename = os.path.basename(the_file)
   chunk_size = 8192
   response = StreamingHttpResponse(FileWrapper(open(the_file, 'rb'), chunk_size),
                           content_type=mimetypes.guess_type(the_file)[0])
   response['Content-Length'] = os.path.getsize(the_file)    
   response['Content-Disposition'] = "attachment; filename=%s" % filename
   return response
Run Code Online (Sandbox Code Playgroud)

  • @azmeuk,来自wsgiref.util的Django 1.9`导入FileWrapper` - 看看这里https://github.com/django/django/commit/bbe28496d32f76ca161f5c33787d6ad62267fcc6#diff-f6d1c75ec606389da5af6558bf57f171 (4认同)
  • 请注意,除了“StreamingHttpResponse”,您还可以使用“FileResponse”:一个流响应,专门用于文件。请参阅 https://docs.djangoproject.com/en/1.9/ref/request-response/#fileresponse-objects (2认同)

Mar*_*rau 14

您可以使用本答案中描述的'sendfile'方法.

实际上你需要这个(c&p):

response = HttpResponse(mimetype='application/force-download')
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(nginxlighty也支持)