You can read the request body directly into a file or bytes. This will read the data from the top level request body, and can only support 1 file. To receive multiple files, see the multipart/form-data documentation.
from xpresso import App, FromFile, Path, UploadFile async def count_bytes_in_file(file: FromFile[UploadFile]) -> int: return len(await file.read()) app = App(routes=[Path(path="/count-bytes", put=count_bytes_in_file)])
UploadFile is a class provided by Starlette that buffers the data in memory and overflows to disk if the data is larger than a predefined threashold.
This prevents a large file from exhausting your hardware's memory.
Xpresso can read the entire file into memory if you'd like:
from xpresso import App, FromFile, Path async def count_bytes_in_file(data: FromFile[bytes]) -> int: return len(data) app = App(routes=[Path(path="/count-bytes", put=count_bytes_in_file)])
This can be convenient if you know the files are not large.
Setting the content-type
You can set the media type via the
media_type parameter to
File() and enforce it via the
from xpresso import App, File, Path, UploadFile from xpresso.typing import Annotated async def count_image_bytes( file: Annotated[ UploadFile, File(media_type="image/*", enforce_media_type=True), ] ) -> int: return len(await file.read()) app = App(routes=[Path(path="/count-bytes", put=count_image_bytes)])
Media types can be a media type (e.g.
image/png) or a media type range (e.g.
If you do not explicitly set the media type, all media types are accepted.
Once you set an explicit media type, that media type in the requests'
Content-Type header will be validated on incoming requests, but this behavior can be disabled via the
enforce_media_type parameter to