I am working with this example in the documentation that shows a basic example of how to work with files.
Is it possible to stream a large file with this? What is the correct pattern?
It's possible to stream files with starlette, so how would integrating this functionality with fastapi work?
Thank you!
Seconded!
I'm also trying to get streaming responses to work, but I haven't had any success so far.
I'm trying to stream a (large) json response to a reactive front-end (vue), which should render the data as is becomes available.
Thanks for any pointers you might have.
Cheers
M
First, for the case of @petermorrownavican , I added a new feature to support UploadFile (from Starlette) in FastAPI, the new documentation is here: https://fastapi.tiangolo.com/tutorial/request-files/#file-parameters-with-uploadfile
That would probably be the best way to deal with large files.
It uses a standard "spooled" file (in memory up to some limit, then on disk).
And you can interact with it as a normal file in Python.
If you have some specific use case that requires you to read the bytes as a stream of content, chunk by chunk (that also means that you don't need to have to whole content/file before starting to read it), you can use the same code as in the example to stream a file with Starlette.
You just have to declare a parameter to take the Starlette Request, and then the same:
async for chunk in request.stream():
...
Adapting the example in Starlette, it would be something similar to:
from fastapi import FastAPI
from starlette.requests import Request
app = FastAPI()
@app.post("/files/")
def create_file(request: Request):
body = b''
async for chunk in request.stream():
body += chunk
response = Response(body, media_type='text/plain')
return response
In the case of @matthdsm , you can return a Starlette StreamingResponse.
It would be similar to:
from fastapi import FastAPI
from starlette.requests import Request
from starlette.responses import StreamingResponse
app = FastAPI()
@app.get("/files/")
def read_stream():
return StreamingResponse(some_generator, media_type='application/json')
But now, have in mind that JSON is a format that needs the whole file to be ready before being parsed. Maybe you have a custom receiver that takes JSON lines separated by new line characters or something similar, but otherwise, if it's pure JSON, your frontend won't be able to parse the contents until you have the full JSON downloaded.
If you need to send different arbitrary JSON messages/documents, you can also think of using WebSockets.
Hi @tiangolo
Thanks for the comprehensive explanation! I got it to work using the example you provided. My front-end will have to be able to receive a json stream, since I'm outputting json objects. I've tried using complete json documents, but in my case, that just doesn't work at all.
I'll look into websockets, thanks for the suggestion!
Cheers
M
Thank you for your quick, thorough and thoughtful responses @tiangolo! The new feature to support UploadFile works perfectly for us.
Awesome! Thanks for reporting back and closing the issue :+1: :taco:
Just out of curiosity, are you using FastAPI at NAVICAN?
We are experimenting with it in dev to see if it meets our needs, but not in production (yet). We like it a lot so far though! 馃憤 馃尟
That's great to hear! I would love to know how it goes.
@tiangolo I am returning a StreamingResponse as suggested above StreamingResponse(image, media_type='image/png') and this works great, but wondering if there is a way to show the response in the documentation rather than showing "null"? Thanks!!

@cmliotta yep, here are the docs: https://fastapi.tiangolo.com/advanced/custom-response/#document-in-openapi-and-override-response
Also here: https://fastapi.tiangolo.com/advanced/additional-responses/
Most helpful comment
First, for the case of @petermorrownavican , I added a new feature to support
UploadFile(from Starlette) in FastAPI, the new documentation is here: https://fastapi.tiangolo.com/tutorial/request-files/#file-parameters-with-uploadfileThat would probably be the best way to deal with large files.
It uses a standard "spooled" file (in memory up to some limit, then on disk).
And you can interact with it as a normal file in Python.
Stream request content
If you have some specific use case that requires you to read the
bytesas a stream of content, chunk by chunk (that also means that you don't need to have to whole content/file before starting to read it), you can use the same code as in the example to stream a file with Starlette.You just have to declare a parameter to take the Starlette
Request, and then the same:Adapting the example in Starlette, it would be something similar to:
Stream response content
In the case of @matthdsm , you can return a Starlette
StreamingResponse.It would be similar to:
But now, have in mind that JSON is a format that needs the whole file to be ready before being parsed. Maybe you have a custom receiver that takes JSON lines separated by new line characters or something similar, but otherwise, if it's pure JSON, your frontend won't be able to parse the contents until you have the full JSON downloaded.
If you need to send different arbitrary JSON messages/documents, you can also think of using
WebSockets.