0

I want to stream a file in telegram using pyrogram, but I can't do it because stream_with_context is not working asynchronously, what can I do?

How can I send a file (bytes) to the user asynchronously via flask? No matter how hard I searched, I could not find the answer to this question, there are always answers for synchronous flasks on the internet.

If I try to use flask synchronously, this time the pyrogram with telegram api starts to cause problems because this api is mainly made for async

from flask import Response

from flask import Flask, send_file
from flask import stream_with_context

app = Flask(__name__)


import asyncio
from pyrogram import Client

api_id = 000
api_hash = ""

tg = Client("aaa", api_id, api_hash)

@app.route('/bigfile')
async def bigfile():
    msg = await tg.get_messages(0674564523, 4564535254)

    async def gnn():
        async for chunk in tg.stream_media(msg):
            chnk = io.BytesIO(chunk)
            yield chnk

    return Response(
        stream_with_context(await gnn()),
        headers={
            'Content-Disposition': f'attachment; filename=asdfasdf.pdf'
        }
    )

import threading


if __name__ == '__main__':
    threading.Thread(target=app.run, daemon=True).start()
    tg.run()
    
Dark
  • 25
  • 4

1 Answers1

0

You can iterate an async iterator manually by applying some glue code:

def iter_over_async(ait, loop):
    ait = ait.__aiter__()
    async def get_next():
        try: obj = await ait.__anext__(); return False, obj
        except StopAsyncIteration: return True, None
    while True:
        done, obj = loop.run_until_complete(get_next())
        if done: break
        yield obj

You can use this to convert an async generator to synchronous in flask.stream_with_context:

async def async_gen():
    for i in range(5):
        yield f"{i}\n"
        await asyncio.sleep(1)

@app.route("/app/async")
def get_data():
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    iter = iter_over_async(async_gen(), loop)
    ctx = flask.stream_with_context(iter)
    response = flask.Response(ctx, content_type='application/json')
    response.headers['X-Accel-Buffering'] = 'no'
    response.headers['Transfer-Encoding'] = 'chunked'
    return response
andronick83
  • 41
  • 1
  • 3