使用大文件烧瓶make_response

时间:2014-06-20 00:03:24

标签: python flask download

所以我真正的绿色文件I / O和内存限制等等,而且我很难让我的Web应用程序成功地将大型文件下载到带有烧瓶的Web浏览器中#&# 39; s make_response。以下代码适用于较小的文件(< ~1GB),但当我进入较大的文件时,我会遇到MemoryError异常:

raw_bytes = ""
with open(file_path, 'rb') as r:
    for line in r:
        raw_bytes = raw_bytes + line
response = make_response(raw_bytes)
response.headers['Content-Type'] = "application/octet-stream"
response.headers['Content-Disposition'] = "inline; filename=" + file_name
return response

我假设将超过2 GB的二进制数据粘贴到一个字符串中可能是一个很大的禁忌,但我不知道如何替代完成这些文件下载黑色魔法。如果有人可以通过粗略的[?]或缓冲的文件下载方法让我走上正轨,或者只是指向一些中级资源以便更深入地了解这些内容,我将非常感激。谢谢!

2 个答案:

答案 0 :(得分:19)

请参阅Streaming Content上的文档。基本上,您编写了一个产生数据块的函数,并将该生成器传递给响应,而不是将整个事件传递给响应。 Flask和您的Web服务器完成剩下的工作。

from flask import stream_with_context, Response

@app.route('/stream_data')
def stream_data():
    def generate():
        # create and return your data in small parts here
        for i in xrange(10000):
            yield str(i)

    return Response(stream_with_context(generate()))

如果文件是静态的,您可以改为利用send_from_directory()。文档建议您使用nginx或其他支持X-SendFile的服务器,以便读取和发送数据是有效的。

答案 1 :(得分:2)

您尝试的问题是,您首先将完整内容读入" raw_bytes",因此对于大文件,您很容易耗尽所有内存。

有多种方法可以解决这个问题:

流式传输内容

正如davidism回答所解释的,你可以使用一个传递给int的生成器。这可以逐个提供大文件,并且不需要太多内存。

流式传输不仅可以来自生成器,还可以来自文件,如shown in this anwer

在烧瓶上提供静态文件

如果您的文件是静态的,请搜索如何配置Flask以提供静态文件。这些应以流媒体方式自动提供。

apachenginx(或其他网络服务器)上提供静态文件

假设该文件是静态的,您将在生产中通过Flask应用程序前面的反向代理服务。这不仅可以卸载您的应用程序,而且还可以更快地运行。