zoukankan      html  css  js  c++  java
  • flask如何使模板返回大文件,又不消耗大量内存

    当我们要往客户端发送大量的数据,比如一个大文件时,将它保存在内存中再一次性发到客户端开销很大。比较好的方式是使用流,本篇就要介绍怎么在Flask中通过流的方式来将响应内容发送给客户端。此外,我们还会演示如何实现文件的上传功能,以及如何获取上传后的文件。

    响应流的生成

    Flask响应流的实现原理就是通过Python的生成器,也就是大家所熟知的yield的表达式,将yield的内容直接发送到客户端。下面就是一个简单的实现:

    这段代码会生成一个5万行100M的csv文件,每一行会通过yield表达式分别发送给客户端。运行时你会发现文件行的生成与浏览器文件的下载是同时进行的,而不是文件全部生成完毕后再开始下载。这里我们用到了响应类”flask.Response”,它是”werkzeug.wrappers.Response”类的一个包装,它的初始化方法第一个参数就是我们定义的生成器函数,第二个参数指定了响应类型。

    我们将上述方法应用到模板中,如果模板的内容很大,怎么采用流的方式呢?这里我们要自己写个流式渲染模板的方法。

    这段代码的核心,就是通过”app.jinja_env”来访问Jinja2的Environment对象,这个我们在Jinja2系列中有介绍,然后调用Environment对象的”get_template()”方法来获得模板对象,再调用模板对象的”stream()”方法生成一个”StreamTemplate”的对象。这个对象实现了”__next__()”方法,可以作为一个生成器使用,如果你看了Jinja2的源码,你会发现模板对象的”stream()”方法的实现就是使用了yield表达式,所以原理同上例一样。另外,我们启用了缓存”enable_buffering()”来避免客户端发送过于频繁,其参数的默认值就是5。

    现在我们就可以在视图方法中,采用”stream_template()”,而不是以前介绍的”render_template()”来渲染模板了:

    上例的代码会将本地的”server.log”日志文件内容传入模板,并以流的方式渲染在页面上。

    另外注意,在生成器中是无法访问请求上下文的。不过Flask从版本0.9开始提供了”stream_with_context()”方法,它允许生成器在运行期间获取请求上下文:

    因为我们初始化Response对象时调用了”stream_with_context()”方法,所以才能在yield表达式中访问request对象。

    转载:

    1、http://www.bjhee.com/flask-ad5.html

  • 相关阅读:
    从零开始学Bootstrap
    CSS VS JS动画,哪个更快
    css定位(positon)
    json
    使用 CSS3 绘制 Hello Kitty
    后台找到repeater里面的div并添加客户端点击事件
    dropDownList之"请选择",同时设置默认选项
    asp.net 后台对话框,确认跳转
    后台生成textbox并设置多行属性,自动换行
    asp.net多图片上传同时保存对每张图片的描述
  • 原文地址:https://www.cnblogs.com/shengulong/p/8072297.html
Copyright © 2011-2022 走看看