microdot.multipart — розбір multipart/form-data

Розбирає тіла запитів Content-Type: multipart/form-data — кодування, яке браузери використовують для форм із полями <input type="file">. Два варіанти API:

  • Потоковий FormDataIter, що генерує поля по одному — корисний, коли застосунок має обробляти дуже великі завантаження частинами на пристрої з обмеженою пам’яттю.

  • Декоратор with_form_data(), що буферизує все і заповнює request.form / request.files — зручний API для завантажень нормального розміру.

class FormDataIter

class microdot.multipart.FormDataIter(request)

Асинхронний ітератор по частинах multipart-тіла request. Генеровані значення — кортежі (name, value); value є str для звичайних полів та FileUpload для файлових полів.

Використовується безпосередньо, коли пам’ять важливіша за зручність:

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'

Примітка

При ітерації по файлових полях файл необхідно прочитати (через FileUpload.read() або FileUpload.save()) до наступної ітерації async for — базовий потік стає недійсним при просуванні ітерації.

buffer_size: int

Атрибут класу. Розмір блоку, що використовується при читанні з потоку запиту. За замовчуванням 256 байт. Збільшіть для вищої пропускної здатності ціною RAM.

class FileUpload

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

Один завантажений файл. Екземпляри генеруються FormDataIter і збираються до request.files через with_form_data(). Застосунки зазвичай не створюють FileUpload безпосередньо.

filename: str

Оригінальна назва файлу, надіслана клієнтом (ненадійна — не передавайте до open() без санітизації).

content_type: str | None

MIME-тип із заголовка Content-Type частини або None, якщо не вказано.

max_memory_size: int

Атрибут класу. Поріг (у байтах), перевищення якого спонукає copy() перейти з буферизації у пам’яті до тимчасового файлу. За замовчуванням 1024.

async read(n: int = -1)

Читає до n байт із потоку завантаження. -1 читає до кінця.

async save(path_or_file)

Зберігає завантаження до path_or_file, що може бути шляхом у файловій системі або вже відкритим файловим об’єктом.

async copy(max_memory_size: int | None = None)

Буферизує завантаження (або в RAM, або у тимчасовому файлі, залежно від max_memory_size), щоб решту multipart-тіла можна було розібрати без зневалідації вихідного потоку. Декоратор with_form_data() викликає це автоматично.

async close()

Звільняє будь-який тимчасовий файл, створений copy(). Викликається автоматично після завершення запиту, якщо завантаження потрапило до request.files через with_form_data().

Декоратори рівня модуля

microdot.multipart.with_form_data(f)

Декоратор, що заздалегідь розбирає multipart-тіло і заповнює request.form та request.files до запуску обробника:

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'

Завантаження файлів буферизуються через FileUpload.copy(), тому обробник може вільно ітерувати request.files та request.form. Тимчасові файли очищаються автоматично після завершення запиту.

Для завантажень розміром більше кількох мегабайт надавайте перевагу потоковому API FormDataIter; with_form_data() накопичує весь запит у пам’яті або у файловій системі до запуску обробника.