基于Flask实现Telegram图片逐张流式展示的方案问询
解决Flask流式展示Telegram图片的问题
问题背景
开发一款从Telegram账号下载媒体并在网页展示的应用,需求是图片在服务器下载过程中逐张显示,但当前所有图片需全部下载完成后才会一同展示。尝试使用yield方法但未达到预期效果,以下是修正后的流式展示方案:
后端代码调整
1. 修改website.py中的接口实现
优化异步生成器处理逻辑,确保每次生成的JSON数据单独成行,方便前端逐行解析:
# website.py from flask import Flask, request, render_template, redirect, url_for, json from All_functions import Telegram_Id_Hash, login_otp_first_half, login_otp_second_half, session_status from All_functions import image_to_html from telethon.sync import TelegramClient import json,os import asyncio from flask import session, Response, stream_with_context @app.route('/Gallary_documents_image_render', methods=['POST']) def Gallary_documents_image_render(): data = session.get('data') api_id, api_hash, number = data['id'], data['hash'], data['number'].replace('+','') async def generate(): client = TelegramClient(number, api_id, api_hash) async for html_code in image_to_html(client=client): # 每次生成JSON后添加换行,作为前端解析的分隔符 yield json.dumps({'html_code': html_code}) + '\n' # 使用Flask的Response配合异步生成器,指定正确的MIME类型 return Response(stream_with_context(generate()), mimetype='text/plain')
2. 确认function.py中的生成器逻辑
确保image_to_html函数正确异步生成HTML片段(无需修改原代码,注意receive_file需为异步实现):
# function.py import base64 # 假设human_readable_size和receive_file已正确实现 async def image_to_html(client): await client.connect() async for message in client.iter_messages('me'): if message.document and message.document.mime_type == 'image/jpeg': image_data=await receive_file(client=client, msg=message) file_name=message.document.attributes[-1].file_name file_size= human_readable_size(message.document.size) date=message.document.date template = f'''<div class="box"> <img src="data:image/jpeg;base64,{base64.b64encode(image_data).decode()}" alt="Telegram Image{date}"> <div class="details"> <p1>{file_name}</p1> <p2>{file_size}</p2> <i class="input_icon uil uil-import"></i> </div> </div>''' yield template await client.disconnect()
前端JavaScript调整
修改gallary.js,处理流式响应的增量内容,逐行解析JSON并渲染HTML:
// gallary.js window.onload = function() { var xhr = new XMLHttpRequest(); xhr.open("POST", "/Gallary_documents_image_render", true); xhr.setRequestHeader("Content-Type", "application/json"); let lastPosition = 0; // 记录上次读取到的位置 const container = document.getElementById("container"); xhr.onprogress = function() { if (xhr.readyState === 3 && xhr.status === 200) { // 获取新增的响应内容 const newContent = xhr.responseText.substring(lastPosition); lastPosition = xhr.responseText.length; // 按换行分割,处理每一行的JSON数据 newContent.split('\n').forEach(line => { if (line.trim()) { try { const data = JSON.parse(line); container.innerHTML += data.html_code; } catch (e) { // 忽略不完整的JSON行(可能还在传输中) } } }); } }; xhr.send(); };
关键修改说明
- 后端:使用异步生成器直接配合Flask Response,避免手动管理事件循环;每个JSON对象后添加换行,作为前端解析的分隔符;将MIME类型改为
text/plain,避免浏览器自动合并响应。 - 前端:使用
onprogress事件监听响应增量,记录上次读取位置,分割每行JSON并解析,避免处理累积的整个响应文本;添加异常处理,忽略未传输完成的不完整JSON行。
内容的提问来源于stack exchange,提问作者Avijit Bhuin
相关产品推荐
相关产品推荐

