Skip to content

Upload Files

Uploading files from your application is something extremely common.

Ravyn handles this by using the UploadFile datastructure object, serving as interface. To make this work you will need to type your uploads accordingly.

UploadFile

To access the UploadFile datastructrure.

from ravyn.core.datastructures import UploadFile

or

from ravyn import UploadFile

Content Types

The body parameter plays a great role when it comes to use the UploadFile. The reason for that is because of the parameter media_type.

The media_type allows to pass different encoding types for your uploads.

Ravyn EncodingType can be accessed via:

from ravyn.utils.enums import EncodingType

The current available content-types available in the EncodingType are:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json

These types are the ones that shall be passed to Body(media_type=...).

Single file upload

Uploading a single file, you need to type the data as UploadFile.

from ravyn import Body, Ravyn, Gateway, JSONResponse, UploadFile, post
from ravyn.utils.enums import EncodingType


@post("/upload")
async def upload_file(
    data: UploadFile = Body(media_type=EncodingType.MULTI_PART),
) -> JSONResponse:
    """
    Uploads a file into the system
    """
    content = await data.read()
    name = data.filename
    return JSONResponse({"filename": name, "content": content.decode()})


app = Ravyn(routes=[Gateway(handler=upload_file, name="upload-file")])

List files upload

In a similar way, you can also access the files as a list.

from typing import Dict, List

from ravyn import Body, Ravyn, Gateway, UploadFile, post
from ravyn.utils.enums import EncodingType


@post("/upload")
async def upload_file(
    data: List[UploadFile] = Body(media_type=EncodingType.MULTI_PART),
) -> Dict[str, str]:
    """
    Uploads a file into the system
    """
    contents = {}
    for file in data:
        content = await file.read()
        contents[file.filename] = content.decode()

    return contents


app = Ravyn(routes=[Gateway(handler=upload_file, name="upload-file")])

Using the File

As mentioned above, File is now fully supported as parameter as well and since File inherits from Body, means all the benefits are also there but is also cleaner as you don't need to specify the media_type=EncodingType.MULTI_PART because it is already the default of File.

Let us see how it looks now using File instead of Body for the uploads.

Single file upload

Uploading a single file, you need to type the data as UploadFile.

from ravyn import Ravyn, File, Gateway, JSONResponse, UploadFile, post


@post("/upload")
async def upload_file(
    data: UploadFile = File(),
) -> JSONResponse:
    """
    Uploads a file into the system
    """
    content = await data.read()
    name = data.filename
    return JSONResponse({"filename": name, "content": content.decode()})


app = Ravyn(routes=[Gateway(handler=upload_file, name="upload-file")])

List files upload

In a similar way, you can also access the files as a list.

from typing import Dict, List

from ravyn import Ravyn, File, Gateway, UploadFile, post


@post("/upload")
async def upload_file(
    data: List[UploadFile] = File(),
) -> Dict[str, str]:
    """
    Uploads a file into the system
    """
    contents = {}
    for file in data:
        content = await file.read()
        contents[file.filename] = content.decode()

    return contents


app = Ravyn(routes=[Gateway(handler=upload_file, name="upload-file")])

Important

Since Body or Field are Pydantic fields (sort of), that also means you can specify for instance, the maximum number of items to be sent in a list for the upload.

from typing import Dict, List

from ravyn import Ravyn, File, Gateway, UploadFile, post


@post("/upload")
async def upload_file(
    data: List[UploadFile] = File(max_length=3),
) -> Dict[str, str]:
    """
    Uploads a file into the system
    """
    contents = {}
    for file in data:
        content = await file.read()
        contents[file.filename] = content.decode()

    return contents


app = Ravyn(routes=[Gateway(handler=upload_file, name="upload-file")])

This means that the maximum number of files allowed for upload using the a list is three. If the maximum is exceeded, it will raise a ValidationErrorException specifying the issues.

Using the max_length is just one attribute available inside File or Body. Since it is derived from pydantic FieldInfo, that means you can also specify other parameters as well.

You can check the list of available parameters default as well.

File from params

The file used with the example as param is not a datastructure but a FieldInfo so it cannot be used to set and create a new file like the one from File in datastructures.

To import it:

from ravyn.core.datastructures import File  # datastructure

# or

from ravyn.params import File  # param

API Reference

Read more about the UploadFile in the API Reference