使用大文件烧瓶make_response

She*_*ork 17 python download flask

所以我真的很喜欢文件I/O和内存限制等等,而且我很难让我的Web应用程序成功地将大文件下载到带有烧瓶的Web浏览器中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
Run Code Online (Sandbox Code Playgroud)

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

dav*_*ism 23

请参阅有关流内容的文档.基本上,你编写一个产生数据块的函数,并将该生成器传递给响应,而不是一次性传递给整个事件.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()))
Run Code Online (Sandbox Code Playgroud)

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


Jan*_*sky 5

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

有多种选择可以解决这个问题:

流式传输内容

正如 davidism answer 所解释的,您可以使用传递给 int Response 的生成器。这一点一点地服务于大文件,不需要那么多内存。

流不仅可以来自生成器,还可以来自文件,如本答案所示

通过烧瓶提供静态文件

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

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

假设文件是​​静态的,你应该在生产中通过反向代理在你的 Flask 应用程序前面提供它。这不仅可以卸载您的应用程序,而且运行速度也更快。