tornado 下载文件,显示下载速度、已下载大小、剩余时间、进度条、文件总大小

news2024/9/27 19:25:28

tornado 下载文件,显示下载速度、已下载大小、剩余时间、进度条、文件总大小

    • 初版
    • 解决中文文件名报错
    • 显示下载速度、已下载大小
    • 下载过程中显示文件总大小、剩余时间、进度条正常前进

初版

import asyncio
import os

import aiofiles
import tornado.web


class FileHandler(tornado.web.RequestHandler):

    async def get(self):
        file_path = self.get_argument("file_path")

        # 验证文件路径是否合法
        if not os.path.exists(file_path):
            self.set_status(404)
            self.write("File not found.")
            return

        if not os.path.isfile(file_path):
            self.set_status(400)
            self.write("Invalid file path: must be a file path.")
            return

        # 获取文件名
        file_name = os.path.basename(file_path)

        self.set_header("Content-Disposition", f"attachment; filename={file_name}")
        self.set_header("Content-Type", "application/octet-stream")

        # 读取文件内容并写入响应
        async with aiofiles.open(file_path, 'rb') as f:
            while True:
                data = await f.read(4096)
                if not data:
                    break
                self.write(data)
        # 结束响应
        self.finish()


def make_app():
    return tornado.web.Application([
        (r"/", FileHandler),
    ])


async def main():
    app = make_app()
    app.listen(8888)
    await asyncio.Event().wait()


if __name__ == "__main__":
    asyncio.run(main())

1

效果:页面会一直卡住,直到文件下载完成才会在下载记录页面显示 0 B/s - 61.0 MB, 共 61.0 MB

  • 下载速度 0 B/s
  • 已下载大小 61.0 MB
  • 文件总大小 61.0 MB
  • 进度条直接 100%,且不会动
  • 剩余时间

显示的都是正确的但都是静态值,不会动。

如果文件名中包含中文会报错如下:

Uncaught exception GET /?file_path=C:\Users\zhaobs\Downloads\%E6%B5%8B%E8%AF%952.exe (::1)
HTTPServerRequest(protocol='http', host='localhost:8888', method='GET', uri='/?file_path=C:\\Users\\zhaobs\\Downloads\\%E6%B5%8B%E8%AF%952.exe', version='HTTP/1.1', remote_ip='::1')
Traceback (most recent call last):
  File "D:\software\anaconda3\envs_dirs\file_download\Lib\site-packages\tornado\web.py", line 1790, in _execute
    result = await result
             ^^^^^^^^^^^^
  File "D:\project\python\file_download\main.py", line 38, in get
    self.finish()
  File "D:\software\anaconda3\envs_dirs\file_download\Lib\site-packages\tornado\web.py", line 1238, in finish
    future = self.flush(include_footers=True)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\software\anaconda3\envs_dirs\file_download\Lib\site-packages\tornado\web.py", line 1175, in flush
    return self.request.connection.write_headers(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\software\anaconda3\envs_dirs\file_download\Lib\site-packages\tornado\http1connection.py", line 450, in write_headers
    lines.extend(line.encode("latin1") for line in header_lines)
  File "D:\software\anaconda3\envs_dirs\file_download\Lib\site-packages\tornado\http1connection.py", line 450, in <genexpr>
    lines.extend(line.encode("latin1") for line in header_lines)
                 ^^^^^^^^^^^^^^^^^^^^^
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 42-43: ordinal not in range(256)
Cannot send error response after headers written
Failed to flush partial response

解决中文文件名报错

关键代码

# 解决中文文件名报错的问题
safe_filename = tornado.escape.url_escape(file_name, plus=False)

self.set_header('Content-Disposition', f'attachment; filename*=UTF-8\'\'{safe_filename}')
class FileHandler(tornado.web.RequestHandler):

    async def get(self):
        file_path = self.get_argument("file_path")

        # 验证文件路径是否合法
        if not os.path.exists(file_path):
            self.set_status(404)
            self.write("File not found.")
            return

        if not os.path.isfile(file_path):
            self.set_status(400)
            self.write("Invalid file path: must be a file path.")
            return

        # 获取文件名
        file_name = os.path.basename(file_path)
        # 解决中文文件名报错的问题
        safe_filename = tornado.escape.url_escape(file_name, plus=False)

        self.set_header('Content-Disposition', f'attachment; filename*=UTF-8\'\'{safe_filename}')
        self.set_header("Content-Type", "application/octet-stream")

        # 读取文件内容并写入响应
        async with aiofiles.open(file_path, 'rb') as f:
            while True:
                data = await f.read(4096)
                if not data:
                    break
                self.write(data)
        # 结束响应
        self.finish()

2

中文文件名已可正常下载

显示下载速度、已下载大小

关键代码

await self.flush()
class FileHandler(tornado.web.RequestHandler):

    async def get(self):
        file_path = self.get_argument("file_path")

        # 验证文件路径是否合法
        if not os.path.exists(file_path):
            self.set_status(404)
            self.write("File not found.")
            return

        if not os.path.isfile(file_path):
            self.set_status(400)
            self.write("Invalid file path: must be a file path.")
            return

        # 获取文件名
        file_name = os.path.basename(file_path)
        # 解决中文文件名报错的问题
        safe_filename = tornado.escape.url_escape(file_name, plus=False)

        self.set_header('Content-Disposition', f'attachment; filename*=UTF-8\'\'{safe_filename}')
        self.set_header("Content-Type", "application/octet-stream")

        # 读取文件内容并写入响应
        async with aiofiles.open(file_path, 'rb') as f:
            while True:
                data = await f.read(4096)
                if not data:
                    break
                self.write(data)
                # 必须添加 flush
                await self.flush()
        # 结束响应
        self.finish()

3

  • 下载速度显示正常
  • 已下载大小显示正常
  • 文件总大小不显示
  • 剩余时间
  • 进度条是假的

下载过程中显示文件总大小、剩余时间、进度条正常前进

关键代码

# 文件大小
file_size = os.path.getsize(file_path)

self.set_header('Content-Length', file_size)
class FileHandler(tornado.web.RequestHandler):

    async def get(self):
        file_path = self.get_argument("file_path")

        # 验证文件路径是否合法
        if not os.path.exists(file_path):
            self.set_status(404)
            self.write("File not found.")
            return

        if not os.path.isfile(file_path):
            self.set_status(400)
            self.write("Invalid file path: must be a file path.")
            return

        # 获取文件名
        file_name = os.path.basename(file_path)
        # 解决中文文件名报错的问题
        safe_filename = tornado.escape.url_escape(file_name, plus=False)
        # 文件大小
        file_size = os.path.getsize(file_path)

        self.set_header('Content-Disposition', f'attachment; filename*=UTF-8\'\'{safe_filename}')
        self.set_header("Content-Type", "application/octet-stream")
        self.set_header('Content-Length', file_size)

        # 读取文件内容并写入响应
        async with aiofiles.open(file_path, 'rb') as f:
            while True:
                data = await f.read(4096)
                if not data:
                    break
                self.write(data)
                # 必须添加 flush
                await self.flush()
        # 结束响应
        self.finish()

4

  • 下载速度显示正常
  • 已下载大小显示正常
  • 显示文件总大小
  • 剩余时间
  • 进度条正常

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1985293.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法刷题日志】1044 最长重复子串和75 颜色分类,

颜色分类 这题就是双指针法&#xff0c;指到1的时候就和p1进行交换&#xff0c;然后p1指针往前移动&#xff0c;指到0的时候就和p0指针进行交换&#xff0c;p0和p1同时往前移动&#xff0c;由于可能出现连续的0后面连续的1&#xff0c;所以为了避免1被交换到末尾&#xff0c;当…

conda-pack基于同一种操作系统的环境打包教程

打包环境总结 1.激活需要复制的虚拟环境 conda env list cd /home/ww/miniconda3/envs/ conda activate webtool 2.将虚拟环境打包&#xff0c;包名&#xff1a;webtool_test.tar.gz conda pack -n webtool -o webtool_test.tar.gz 3.创建虚拟环境文件夹&#xff0c;把打包的…

Python实现深度森林(Deep Forest)分类模型(deepforest分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 随着大数据时代的到来&#xff0c;机器学习技术在各个领域的应用变得越来越广泛。在许多实际问题中&am…

HCIP学习 | 广域网、OSPF基础

Days03&#xff08;24.8.4&#xff09;广域网技术 概述 广域网技术在数据链路层面针对不同的物理链路定义了不同的封装方式。‌ 对于局域网封装&#xff0c;‌主要有Ethernet 2&#xff08;‌基于TCP/IP开发&#xff09;‌和IEEE802.3&#xff08;‌基于OSI协议开发&#xff0…

红黑树的概念和模拟实现[C++]

文章目录 红黑树的概念一、红黑树的性质红黑树原理二、红黑树的优势和比较 红黑树的模拟实现构建红黑树的数据结构定义节点的基本结构和初始化方式插入新节点插入新节点的颜色调整颜色和结构以满足红黑树性质 红黑树的应用场景 红黑树的概念 一、红黑树的性质 红黑树是一种自平…

强类型语言、弱类型语言、静态类型语言、动态类型语言

强类型和弱类型&#xff0c;并没有严格绝对的界限&#xff0c;比如C/C这种典型的强类型语言&#xff0c;实际上也允许一些隐式类型传换。

一六二、记node-sass安装失败和node切换失败问题

1. 项目install失败 2. 查询问题 在stackoverflow查询到error /node_modules/node-sass: Command failed&#xff0c;明白是node版本和node-sass版本不匹配 查询自己的node版本 应该是node版本太高的问题 3. 切换node版本 使用n切换node版本失败 原因&#xff1a;而 n 默…

2-Linux系统概述

Linux系统概述 创始人——林纳斯托瓦兹&#xff0c;Linux诞生于1991年&#xff0c;作者上大学期间实现的&#xff0c;Linux的特点&#xff1a;开源、免费、拥有最为庞大的源码贡献者&#xff1b;Linux的吉祥物是企鹅 区别开源和闭源 开源&#xff1a;开放程序源代码&#xff0…

前端(五):前端工程化

前端工程化是指在企业级的前端开发项目中&#xff0c;把前端开发所需的工具、技术、流程、经验等进行规范化、标准化。 一、环境准备 &#xff08;一&#xff09;环境准备 1、Vue-cli&#xff1a;是Vue官方提供的一个脚手架&#xff0c;用于快速生成一个Vue的项目模板。 2、…

如何利用WMS仓储管理系统进行库存整合

在当今竞争激烈的市场环境中&#xff0c;库存管理已成为企业运营的核心环节之一。为了提高库存管理的效率&#xff0c;降低库存成本&#xff0c;并实现库存资源的有效整合&#xff0c;越来越多的企业开始转向采用WMS仓储管理系统解决方案这一智能化工具。本文将从库存整合的迫切…

矩阵获客时代,云微客布局SEO优化,提升企业搜索流量

矩阵这个词大家应该都不是第一次听了&#xff0c;毕竟现在互联网时代&#xff0c;想要在线上获客&#xff0c;矩阵就绕不过去的。现在&#xff0c;短视频已经成为了当下年轻人获取信息的重要途径&#xff0c;而对于商企来说&#xff0c;布局短视频矩阵不仅是线上获客、获取流量…

内网域森林之ProxyNotShell漏洞利用

点击星标&#xff0c;即时接收最新推文 本文选自《内网安全攻防&#xff1a;红队之路》 在渗透测试过程&#xff0c;如果目标环境存在Exchange服务器&#xff0c;我们也需要测试是否存在已知的远程命令执行漏洞&#xff0c;这里首先介绍ProxyNotShell。 ProxyNotShell和之前…

60 函数参数——关键参数

关键参数主要指调用函数时的参数传递方式&#xff0c;与函数定义无关。 通过关键参数可以按参数名字传递值&#xff0c;明确指定哪个值传递给哪个参数&#xff0c;实参顺序可以和形参顺序不一致&#xff0c;但不影响参数值的传递结果&#xff0c;避免了用户需要牢记参数位置和…

战锤40K极速狂飙怎么领 战锤40K极速狂飙免费喜加一入库教程

steam喜加一。游戏名称叫做《战锤40K&#xff1a;极速狂飙&#xff08;Warhammer 40,000: Speed Freeks&#xff09;》&#xff0c;这是一款背景设定在《战锤40K》宇宙中的竞速游戏&#xff0c;玩家将驾驶装载着炸裂性武器和强大能力的车辆&#xff0c;在肾上腺素爆棚的竞速比赛…

非标自动化ARM供控制器用于绕线机控制解决方案

在现代工业生产中&#xff0c;绕线机是一种广泛应用的设备&#xff0c;用于制造各种线圈和绕组。而绕线机的控制精度和速度直接影响到产品的质量和生产效率。ARMxy 嵌入式电脑作为一种高性能的控制设备&#xff0c;为绕线机控制带来了新的标准。 ARMxy 嵌入式电脑采用了先进的嵌…

计算机毕业设计选题推荐-课程教学平台-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

从零开始学python必看,最强“Python编程三剑客(pdf)”,拿来吧你!

从0开始学Python&#xff0c;就问你一句&#xff1a;慌不慌&#xff1f; 说句实在的&#xff0c;慌&#xff0c;可能是因为你自己没有完整的规划&#xff0c;其实就是不知道从何下手&#xff0c;七七八八乱学一通自然还是觉得无厘头。 但今天&#xff0c;我要跟你讲&#xff…

用户资产分级分类、命名和编码规则设计(汽车行业)

用户资产设计目的 用户资产建设要求聚合跨触点数据&#xff0c;对数据进行清洗、转换、整合&#xff0c;实现数据标准化、集成化、用户资产化&#xff0c;沉淀共性数据服务能力、以快速响应业务需求。 为支撑数据融通共享、数据分析挖掘和数据运营&#xff0c;形成数据业务化…

Python实现深度森林(Deep Forest)回归模型(deepforest回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 随着大数据和人工智能技术的发展&#xff0c;机器学习已成为解决各种复杂问题的强大工具。在众多机器学…

采用Spring Cloud +UniApp +MySql技术开发,SaaS模式的一套智慧工地云平台源码,支持多端展示:PC端、大屏端、手机端、平板端

基于微服务架构JavaSpring Cloud UniApp MySql技术开发saas模式的一套智慧工地云平台源码&#xff0c;支持多端展示&#xff1a;PC端、大屏端、手机端、平板端。 智慧工地平台支持项目级、公司级、集团级多级权限划分&#xff0c;可根据企业的组织架构进行项目权限、功能权限、…