Flask用大文件作出反应

2024-04-25 22:59:30 发布

您现在位置:Python中文网/ 问答频道 /正文

因此,我对文件I/O和内存限制等非常熟悉,而且我很难让我的web应用程序成功地将大文件下载服务到带有flask的make_response的web浏览器中。以下代码适用于较小的文件(<;~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

我假设将超过2GB的二进制数据粘贴到一个字符串中可能是一个很大的禁忌,但是我不知道除了完成这些文件下载的黑魔法之外还有什么其他选择。如果有人能帮我找到一个合适的方向?]或者是文件下载的缓冲方法,或者只是指给我一些中间级别的资源来帮助我更深入地理解这些东西,我会非常感激。谢谢!


Tags: 文件内存代码web应用程序flaskrawmake
2条回答

你尝试的问题是,你首先要把完整的内容读入“原始字节”,因此对于大文件,你很容易耗尽所有的内存。

有多种解决方案:

流式传输内容

正如davidism answer所解释的,可以使用生成器传递的int响应。这是一个接一个地为大文件服务,不需要太多内存。

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

在烧瓶上提供静态文件

如果您的文件是静态的,请搜索如何配置烧瓶来提供静态文件。应以流式方式自动送达。

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

假设文件是静态的,那么在生产中,您应该在烧瓶应用程序前通过反向代理服务它。这不仅可以卸载你的应用程序,而且可以更快地工作。

请参阅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()))

如果文件是静态的,则可以利用^{}。这些文档建议您使用nginx或其他支持X-SendFile的服务器,这样读取和发送数据就更加高效。

相关问题 更多 >