提供大文件的Django Filewrapper内存错误,如何流式传输 [英] Django Filewrapper memory error serving big files, how to stream

查看:210
本文介绍了提供大文件的Django Filewrapper内存错误,如何流式传输的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的代码:

@login_required
def download_file(request):
    content_type = "application/octet-stream"
    download_name = os.path.join(DATA_ROOT, "video.avi")

    with open(download_name, "rb") as f:
        wrapper = FileWrapper(f, 8192)
        response = HttpResponse(wrapper, content_type=content_type)
    response['Content-Disposition'] = 'attachment; filename=blabla.avi'
    response['Content-Length'] = os.path.getsize(download_name)
    # response['Content-Length'] = _file.size
    return response

似乎可行。但是,如果我下载更大的文件(例如〜600MB),则内存消耗将增加600MB。经过几次这样的下载后,我的服务器抛出了一个错误:

It seems that it works. However, If I download bigger file (~600MB for example) my memory consumption increase by this 600MB. After few such a downloads my server throws:


内部服务器错误:/ download / Traceback(最近一次调用):

文件
/home/matous/.local/lib/python3.5/site-packages/django/core/handlers/exception.py\",
第35行,位于内部
response = get_response(request)文件 /home/matous/.local/lib/python3.5/site-packages/django/core/handlers/base.py,
第128行,在_get_response $ b $中b响应= self.process_exception_by_middleware(e,request)文件 /home/matous/.local/lib/python3.5/site-packages/django/core/handlers/base.py\",
行126,在_get_response
response = wraped_callback(request,* callback_args,** callback_kwargs)文件 /home/matous/.local/lib/python3.5/site-packages/django/contrib/auth/decorators.py,
第21行,在_wrapped_view
中,返回view_func(request,* args,** kwargs)File / media / matous / 89104d3d-fa52-4b14-9c5d-9ec54ceebebb / home / matous / phd / emoapp / emoapp / mainapp /views.py\",
行118,在download_file
response = HttpResponse(wrapper,content_type = content_type)文件 /home/matous/.local/lib/python3.5/site-packages/django /http/response.py,
行285,在 init 中,
self.content = content文件 /home/matous/.local/lib/python3.5/site -packages / django / http / response.py,
行308,内容为
content = b''。join(self.make_bytes(chunk)表示值的块)MemoryError

Internal Server Error: /download/ Traceback (most recent call last):
File "/home/matous/.local/lib/python3.5/site-packages/django/core/handlers/exception.py", line 35, in inner response = get_response(request) File "/home/matous/.local/lib/python3.5/site-packages/django/core/handlers/base.py", line 128, in _get_response response = self.process_exception_by_middleware(e, request) File "/home/matous/.local/lib/python3.5/site-packages/django/core/handlers/base.py", line 126, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/home/matous/.local/lib/python3.5/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view return view_func(request, *args, **kwargs) File "/media/matous/89104d3d-fa52-4b14-9c5d-9ec54ceebebb/home/matous/phd/emoapp/emoapp/mainapp/views.py", line 118, in download_file response = HttpResponse(wrapper, content_type=content_type) File "/home/matous/.local/lib/python3.5/site-packages/django/http/response.py", line 285, in init self.content = content File "/home/matous/.local/lib/python3.5/site-packages/django/http/response.py", line 308, in content content = b''.join(self.make_bytes(chunk) for chunk in value) MemoryError

我在做什么错?

注意:我知道不应该提供大文件,是否可以通过某种方式对其进行配置,使其从硬盘驱动器逐流传输?

Note: I know that big files should not be served by Django, but I am looking for simple approach that allows to verify user access rights for any served file.

推荐答案

尝试使用 StreamingHttpResponse 相反,这会有所帮助,这正是您要寻找的东西。

Try to use StreamingHttpResponse instead, that will help, it is exactly what you are looking for.

是否可能配置它以某种方式将其从硬盘驱动器逐个流传输而没有这种疯狂的内存存储?

import os
from django.http import StreamingHttpResponse
from django.core.servers.basehttp import FileWrapper #django <=1.8
from wsgiref.util import FileWrapper #django >1.8

@login_required
def download_file(request):
   file_path = os.path.join(DATA_ROOT, "video.avi")
   filename = os.path.basename(file_path)
   chunk_size = 8192
   response = StreamingHttpResponse(
       FileWrapper(open(file_path, 'rb'), chunk_size),
       content_type="application/octet-stream"
   )
   response['Content-Length'] = os.path.getsize(file_path)    
   response['Content-Disposition'] = "attachment; filename=%s" % filename
   return response

这将分批传输文件,而不会将其加载到内存中;或者,您可以使用 FileResponse

This will stream your file in chunks without loading it in memory; alternatively, you can use FileResponse,


这是 StreamingHttpResponse 的子类,已为二进制$ b $优化b个文件。

which is a subclass of StreamingHttpResponse optimized for binary files.

这篇关于提供大文件的Django Filewrapper内存错误,如何流式传输的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆