microdot.multipart — parsen van multipart/form-data

Parseert Content-Type: multipart/form-data-requestbodies – de codering die browsers gebruiken voor formulieren met <input type="file">-velden. Twee varianten van de API:

  • Een streamende FormDataIter die velden één voor één oplevert – handig wanneer de applicatie zeer grote uploads stuk voor stuk moet verwerken op een apparaat met beperkt geheugen.

  • Een with_form_data()-decorator die alles buffert en request.form / request.files vult – de handige API voor uploads van normale grootte.

class FormDataIter

class microdot.multipart.FormDataIter(request)

Async iterator over de onderdelen van de multipart-body van request. De opgeleverde waarden zijn (name, value)-tuples; value is een str voor reguliere velden en een FileUpload voor bestandsvelden.

Wordt rechtstreeks gebruikt wanneer geheugen belangrijker is dan ergonomie:

from microdot.multipart import FormDataIter, FileUpload

@app.post('/upload')
async def upload(request):
    async for name, value in FormDataIter(request):
        if isinstance(value, FileUpload):
            await value.save('/sdcard/' + value.filename)
        else:
            print(name, '=', value)
    return 'ok'

Notitie

Bij het itereren over bestandsvelden moet het bestand verwerkt zijn (via FileUpload.read() of FileUpload.save()) voordat de volgende async for-iteratie plaatsvindt – de onderliggende stream wordt ongeldig wanneer de iteratie verdergaat.

buffer_size: int

Klasse-attribuut. Brokgrootte die wordt gebruikt bij het lezen uit de requeststream. Standaard 256 bytes. Verhoog dit voor een hogere doorvoer ten koste van RAM.

class FileUpload

class microdot.multipart.FileUpload(filename: str, content_type: str | None, read)

Een enkel geüpload bestand. Instanties worden opgeleverd door FormDataIter en verzameld in request.files door with_form_data(). Applicaties construeren normaal gesproken niet rechtstreeks een FileUpload.

filename: str

De oorspronkelijke naam van het bestand zoals de client deze verstuurde (niet vertrouwd – geef deze niet door aan open() zonder opschoning).

content_type: str | None

Het MIME-type uit de Content-Type-header van het onderdeel, of None indien niet opgegeven.

max_memory_size: int

Klasse-attribuut. Drempelwaarde (in bytes) waarboven copy() overschakelt van buffering in het geheugen naar een tijdelijk bestand. Standaard 1024.

async read(n: int = -1)

Lees maximaal n bytes uit de uploadstream. -1 leest tot het einde.

async save(path_or_file)

Sla de upload op naar path_or_file, wat een bestandssysteempad of een reeds geopend bestandsobject kan zijn.

async copy(max_memory_size: int | None = None)

Buffer de upload (ofwel in RAM ofwel in een tijdelijk bestand, afhankelijk van max_memory_size) zodat de rest van de multipart-body geparseerd kan worden zonder dat de oorspronkelijke stream ongeldig wordt. De with_form_data()-decorator roept dit automatisch aan.

async close()

Geef een eventueel door copy() aangemaakt tijdelijk bestand vrij. Wordt automatisch aangeroepen wanneer het verzoek eindigt als de upload via with_form_data() in request.files terecht is gekomen.

Decorators op moduleniveau

microdot.multipart.with_form_data(f)

Decorator die de multipart-body vooraf parseert en request.form en request.files vult voordat de handler wordt uitgevoerd:

from microdot import Microdot
from microdot.multipart import with_form_data

app = Microdot()

@app.post('/upload')
@with_form_data
async def upload(request):
    print('fields:', dict(request.form))
    for name, file in request.files.items():
        await file.save('/sdcard/' + sanitize(file.filename))
    return 'ok'

Bestandsuploads worden gebufferd via FileUpload.copy(), zodat de handler vrij over request.files en request.form kan itereren. Tijdelijke bestanden worden automatisch opgeruimd wanneer het verzoek eindigt.

Geef voor uploads groter dan een paar megabyte de voorkeur aan de streamende FormDataIter-API; with_form_data() accumuleert het volledige verzoek in het geheugen of op het bestandssysteem voordat de handler wordt uitgevoerd.