tornado总结7-文件切片异步非阻塞下载

目标

  文件切片,每一片都进行异步下载python

  影响是增长了文件的下载时间ios

 

代码

import os
import stat

import tornado.gen
import tornado.httpserver
import tornado.ioloop
import tornado.web
from tornado import iostream


class DownloadHandler(tornado.web.RequestHandler):
    @tornado.gen.coroutine
    def get(self):
        file_path = './a.zip'
        content_length = self.get_content_size(file_path)
        self.set_header("Content-Length", content_length)
        self.set_header("Content-Type", "application/octet-stream")
        self.set_header("Content-Disposition", "attachment;filename=\"{0}\"".format("a.data")) #设置新的文件名
        content = self.get_content(file_path)
        if isinstance(content, bytes):
            content = [content]
        for chunk in content:
            try:
                self.write(chunk)
                yield self.flush()
            except iostream.StreamClosedError:
                break
        return

    # 使用python自带的对于yield的应用对文件进行切片,for循环每运用一次就调用一次
    def get_content(self, file_path):
        start=None
        end=None
        with open(file_path, "rb") as file:
            if start is not None:
                file.seek(start)
            if end is not None:
                remaining = end - (start or 0)
            else:
                remaining = None
            while True:
                chunk_size = 64 * 1024 #每片的大小是64K
                if remaining is not None and remaining < chunk_size:
                    chunk_size = remaining
                chunk = file.read(chunk_size)
                if chunk:
                    if remaining is not None:
                        remaining -= len(chunk)
                    yield chunk
                else:
                    if remaining is not None:
                        assert remaining == 0
                    return

    # 读取文件长度
    def get_content_size(self, file_path):
        stat_result = os.stat(file_path)
        content_size = stat_result[stat.ST_SIZE]
        return content_size


class HelloHandler(tornado.web.RequestHandler):
    def get(self):
        return self.finish("Hello Tornado")

class Application(tornado.web.Application):
    def __init__(self):

        handlers = [
            (r"/download", DownloadHandler),
            (r".*?", HelloHandler),
        ]

        tornado.web.Application.__init__(self, handlers)


if __name__ == "__main__":
    port = 8899
    application = Application()
    http_server = tornado.httpserver.HTTPServer(application, xheaders=True)
    http_server.listen(port)

    print('Listen on http://localhost:{0}'.format(port))
    tornado.ioloop.IOLoop.instance().start()

"/download"路由的Get方法调用时,将会进行一个文件下载操做,将同目录下的a.zip文件切片下载为a.data文件。web

下载过程当中,会空出一些时间间隙,让tornado继续处理其余类型的请求。app

下载过程综合了python和tornado对yield的应用。异步

相关文章
相关标签/搜索