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的應用。異步

相關文章
相關標籤/搜索