1# Stream Data { #stream-data }23If you want to stream data that can be structured as JSON, you should [Stream JSON Lines](../tutorial/stream-json-lines.md).45But if you want to **stream pure binary data** or strings, here's how you can do it.67/// note89Added in FastAPI 0.134.0.1011///1213## Use Cases { #use-cases }1415You could use this if you want to stream pure strings, for example directly from the output of an **AI LLM** service.1617You could also use it to stream **large binary files**, where you stream each chunk of data as you read it, without having to read it all into memory at once.1819You could also stream **video** or **audio** this way, it could even be generated as you process and send it.2021## A `StreamingResponse` with `yield` { #a-streamingresponse-with-yield }2223If you declare a `response_class=StreamingResponse` in your *path operation function*, you can use `yield` to send each chunk of data in turn.2425{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *}2627FastAPI will give each chunk of data to the `StreamingResponse` as is, it won't try to convert it to JSON or anything similar.2829### Non-async *path operation functions* { #non-async-path-operation-functions }3031You can also use regular `def` functions (without `async`), and use `yield` the same way.3233{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *}3435### No Annotation { #no-annotation }3637You don't really need to declare the return type annotation for streaming binary data.3839As FastAPI will not try to convert the data to JSON with Pydantic or serialize it in any way, in this case, the type annotation is only for your editor and tools to use, it won't be used by FastAPI.4041{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *}4243This also means that with `StreamingResponse` you have the **freedom** and **responsibility** to produce and encode the data bytes exactly as you need them to be sent, independent of the type annotations. 🤓4445### Stream Bytes { #stream-bytes }4647One of the main use cases would be to stream `bytes` instead of strings, you can of course do it.4849{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *}5051## A Custom `PNGStreamingResponse` { #a-custom-pngstreamingresponse }5253In the examples above, the data bytes were streamed, but the response didn't have a `Content-Type` header, so the client didn't know what type of data it was receiving.5455You can create a custom sub-class of `StreamingResponse` that sets the `Content-Type` header to the type of data you're streaming.5657For example, you can create a `PNGStreamingResponse` that sets the `Content-Type` header to `image/png` using the `media_type` attribute:5859{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *}6061Then you can use this new class in `response_class=PNGStreamingResponse` in your *path operation function*:6263{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *}6465### Simulate a File { #simulate-a-file }6667In this example, we are simulating a file with `io.BytesIO`, which is a file-like object that lives only in memory, but lets us use the same interface.6869For example, we can iterate over it to consume its contents, as we could with a file.7071{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *}7273/// note | Technical Details7475The other two variables, `image_base64` and `binary_image`, are an image encoded in Base64, and then converted to bytes, to then pass it to `io.BytesIO`.7677Only so that it can live in the same file for this example and you can copy it and run it as is. 🥚7879///8081By using a `with` block, we make sure that the file-like object is closed after the generator function (the function with `yield`) is done. So, after it finishes sending the response.8283It wouldn't be that important in this specific example because it's a fake in-memory file (with `io.BytesIO`), but with a real file, it would be important to make sure the file is closed after the work with it is done.8485### Files and Async { #files-and-async }8687In most cases, file-like objects are not compatible with async and await by default.8889For example, they don't have an `await file.read()`, or `async for chunk in file`.9091And in many cases, reading them would be a blocking operation (that could block the event loop), because they are read from disk or from the network.9293/// note9495The example above is actually an exception, because the `io.BytesIO` object is already in memory, so reading it won't block anything.9697But in many cases reading a file or a file-like object would block.9899///100101To avoid blocking the event loop, you can simply declare the *path operation function* with regular `def` instead of `async def`, that way FastAPI will run it on a threadpool worker, to avoid blocking the main loop.102103{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *}104105/// tip106107If you need to call blocking code from inside of an async function, or an async function from inside of a blocking function, you could use [Asyncer](https://asyncer.tiangolo.com), a sibling library to FastAPI.108109///110111### `yield from` { #yield-from }112113When you are iterating over something, like a file-like object, and then you are doing `yield` for each item, you could also use `yield from` to yield each item directly and skip the `for` loop.114115This is not particular to FastAPI, it's just Python, but it's a nice trick to know. 😎116117{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *}
Findings
✓ No findings reported for this file.