Pyrogram异步流式传输异常及Flask异步文件发送技术求助
问题分析
你的代码存在几个核心问题:
- Flask默认的
stream_with_context仅支持同步生成器,无法直接处理Pyrogram返回的异步流 - 用多线程分开运行Flask和Pyrogram会导致事件循环隔离,异步调用Pyrogram API时会出现跨线程事件循环冲突
- 错误地
await异步生成器,且不必要地将chunk转为BytesIO(直接yield原始字节即可)
解决方案步骤
1. 升级到异步兼容的Flask环境
确保使用Flask 2.0+版本,同时使用支持异步的服务器(如uvicorn或hypercorn),替代默认的werkzeug服务器。
2. 统一事件循环,避免多线程冲突
不要用threading分开运行Flask和Pyrogram,而是在同一个事件循环中启动两者。
3. 正确处理异步流到Flask Response
将Pyrogram的异步流转换为Flask可处理的格式,直接在异步视图中返回字节流。
修正后的完整代码
from flask import Flask, Response import asyncio from pyrogram import Client import uvicorn # 配置Telegram API信息 api_id = 000 api_hash = "" chat_id = 0674564523 # 单独提取变量,提高可读性 message_id = 4564535254 app = Flask(__name__) tg = Client("aaa", api_id, api_hash) @app.route('/bigfile') async def bigfile(): # 获取目标消息 msg = await tg.get_messages(chat_id, message_id) # 异步生成器:流式获取Telegram文件字节 async def file_stream(): async for chunk in tg.stream_media(msg): yield chunk # 直接返回原始字节,无需包装成BytesIO # 返回Response,指定下载头 return Response( file_stream(), headers={ 'Content-Disposition': 'attachment; filename=downloaded_file.pdf', 'Content-Type': 'application/pdf' # 指定正确的MIME类型,帮助浏览器识别文件 } ) async def main(): # 启动Pyrogram客户端 await tg.start() # 启动uvicorn服务器 config = uvicorn.Config(app, host="0.0.0.0", port=5000) server = uvicorn.Server(config) await server.serve() if __name__ == '__main__': asyncio.run(main())
关键修改说明
- 移除多线程:用
asyncio.run()统一管理Pyrogram和Flask的事件循环,彻底避免跨线程事件冲突 - 简化生成器:直接yield Pyrogram返回的原始字节,省去不必要的
BytesIO包装 - 使用异步服务器:用
uvicorn替代默认Flask服务器,原生支持异步视图和流式响应 - 明确MIME类型:在Response头中指定
Content-Type,确保浏览器正确处理下载文件
运行方式
- 安装依赖:
pip install flask pyrogram uvicorn
- 运行脚本后,访问
http://localhost:5000/bigfile即可流式下载Telegram中的文件
内容的提问来源于stack exchange,提问作者Dark
相关产品推荐
相关产品推荐

