sanic-org / sanic

Accelerate your web app development | Build fast. Run fast.
https://sanic.dev
MIT License
18k stars 1.54k forks source link

Response.file send in-memory file #1485

Closed mojimi closed 5 years ago

mojimi commented 5 years ago

I'm trying to migrate from Flask, and a very common case for me is generating large in-memory excel files and returning them without saving to disk.

Is this not possible with Sanic? Is there any workaround that doesn't involve modifying the framework?

More specific, I'm looking for a way to send a BytesIO object as response.

sjsadowski commented 5 years ago

https://sanic.readthedocs.io/en/latest/sanic/streaming.html#response-streaming

mojimi commented 5 years ago

https://sanic.readthedocs.io/en/latest/sanic/streaming.html#response-streaming

I did see that, pardon me but I don't understand how it is related to sending a BytesIO object

sjsadowski commented 5 years ago

You could set your content type and stream the object out.

mojimi commented 5 years ago

You could set your content type and stream the object out.

Could an example be provided? I don't really understand what a stream it.

Here's what I've tried :

@app.route('/xlsx/table')
async def xlsx(request):
    output = BytesIO(generateExcelAsBytes())
    body = output.getvalue()
    headers = {
        'Content-Disposition': 'attachment; filename="{}"'.format(filename),
    }
    content_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    return response.raw(body=body,headers=headers,content_type=content_type)

But I get error :


[2019-02-05 15:04:13 -0200] [12592] [ERROR] Invalid response object for url b'/xlsx/table', Expected Type: HTTPResponse, Actual Type: <class 'NoneType'>
[2019-02-05 15:04:13 -0200] [12592] [ERROR] Exception occurred while handling uri: 'http://localhost:8000/xlsx/table'
Traceback (most recent call last):
  File "C:\projects\python-rest\py-37\lib\site-packages\sanic\server.py", line 374, in write_response
    response.output(
AttributeError: 'NoneType' object has no attribute 'output'
sjsadowski commented 5 years ago

There are two examples provided in the documentation linked above. If you need more help, please join us over at the community and ask for assistance there: https://community.sanicframework.org/

KTibow commented 1 year ago

sorry for bumping an old issue but could someone give a working example of streaming bytesio to a response? ive tried some stuff, googled around, and checked the forums but couldnt find anything

ahopkins commented 1 year ago

Just read from it and send chunks (or the entire thing) as you would with any streaming response:

@app.get("/")
async def handler(request: Request):
    something = BytesIO(b"fee fi fo fum")
    resp = await request.respond(content_type="text/plain")

    while True:
        read = something.read(2)
        if not read:
            break
        await resp.send(read)

For further support and discussion: https://sanic.dev/en/help.html