Flask:使用stream_with_context的流式文件非常慢

时间:2015-12-11 17:37:29

标签: flask flask-sqlalchemy

以下代码将postgres BYTEA列流式传输到浏览器

from flask import Response, stream_with_context

@app.route('/api/1/zfile/<file_id>', methods=['GET'])
def download_file(file_id):

    file = ZFile.query.filter_by(id=file_id).first()
    return Response(stream_with_context(file.data), mimetype=file.mime_type)

速度非常慢(每5分钟大约6分钟)。

我正在使用curl从同一主机下载,因此网络不是问题, 我也可以在不到一秒的时间内从psql控制台中提取文件, 所以看来数据库方面也不应该受到责备:

COPY (select f.data from z_file f where f.id = '4ec3rf') TO 'zazX.pdf' (FORMAT binary)

更新

我还有进一步的证据表明&#34;从数据库中获取&#34;步骤不慢,如果我使用

将file.data写入文件
with open("/vagrant/zoz.pdf", 'wb') as output:
    output.write(file.data)

它也需要几分之一秒。因此,缓慢是由Flask进行流式传输的方式引起的。

2 个答案:

答案 0 :(得分:2)

我在使用Flask使用python-requests代理来自其他网址的流媒体时遇到了这个问题。

在这个用例中,诀窍是在iter_content中设置chunk_size参数:

def flask_view():
    ...
    req = requests.get(url, stream=True, params=args)
    return Response(
        stream_with_context(req.iter_content(chunk_size=1024)),
        content_type=req.headers['content-type']

否则它会使用chunk_size = 1,这可能会使事情变慢。在我的情况下,在chunk_size增加之后,流式传输从几kb / s到几mb / s。

答案 1 :(得分:0)

Flask可以被赋予一个生成器,它以单个yield返回整个数组,并且“知道”如何处理它,这将以毫秒为单位返回:

from flask import Response, stream_with_context

@app.route('/api/1/zfile/<file_id>', methods=['GET'])
def download_file(file_id):

    file = ZFile.query.filter_by(id=file_id).first()

    def single_chunk_generator():
        yield file.data

    return Response(stream_with_context(single_chunk_generator()), mimetype=file.mime_type)

stream_with_context ,当给定数组时,将创建一个生成器,迭代它并对每个元素进行各种检查,这会导致巨大的性能损失。