You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

11 KiB

Запит файлів

Ви можете визначити файли, які будуть завантажуватися клієнтом, використовуючи File.

/// info | Інформація

Щоб отримувати завантажені файли, спочатку встановіть python-multipart.

Переконайтеся, що Ви створили віртуальне середовище{.internal-link target=_blank}, активували його та встановили пакет, наприклад:

$ pip install python-multipart

Це необхідно, оскільки завантажені файли передаються у вигляді "форматованих даних форми".

///

Імпорт File

Імпортуйте File та UploadFile з fastapi:

{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}

Визначення параметрів File

Створіть параметри файлів так само як Ви б створювали Body або Form:

{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}

/// info | Інформація

File — це клас, який безпосередньо успадковує Form.

Але пам’ятайте, що коли Ви імпортуєте Query, Path, File та інші з fastapi, це насправді функції, які повертають спеціальні класи.

///

/// tip | Підказка

Щоб оголосити тіла файлів, Вам потрібно використовувати File, тому що інакше параметри будуть інтерпретовані як параметри запиту або параметри тіла (JSON).

///

Файли будуть завантажені у вигляді "форматованих даних форми".

Якщо Ви оголосите тип параметра функції обробника маршруту як bytes, FastAPI прочитає файл за Вас, і Ви отримаєте його вміст у вигляді bytes.

Однак майте на увазі, що весь вміст буде збережено в пам'яті. Це працюватиме добре для малих файлів.

Але в деяких випадках Вам може знадобитися UploadFile.

Параметри файлу з UploadFile

Визначте параметр файлу з типом UploadFile:

{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *}

Використання UploadFile має кілька переваг перед bytes:

  • Вам не потрібно використовувати File() у значенні за замовчуванням параметра.
  • Використовується "буферизований" файл:
    • Файл зберігається в пам'яті до досягнення певного обмеження, після чого він записується на диск.
  • Це означає, що він добре працює для великих файлів, таких як зображення, відео, великі двійкові файли тощо, не споживаючи всю пам'ять. Ви можете отримати метадані про завантажений файл.
  • Він має file-like асинхронний файловий інтерфейс interface.
  • Він надає фактичний об'єкт Python SpooledTemporaryFile, який можна передавати безпосередньо іншим бібліотекам.

UploadFile

UploadFile має такі атрибути:

  • filename: Рядок str з оригінальною назвою файлу, який був завантажений (наприклад, myimage.jpg).
  • content_type: Рядок str з MIME-типом (наприклад, image/jpeg).
  • file: Об'єкт SpooledTemporaryFile (файлоподібний об'єкт). Це фактичний файловий об'єкт Python, який можна безпосередньо передавати іншим функціям або бібліотекам, що очікують "файлоподібний" об'єкт.

UploadFile має такі асинхронні async методи. Вони викликають відповідні методи файлу під капотом (використовуючи внутрішній SpooledTemporaryFile).

  • write(data): Записує data (str або bytes) у файл.
  • read(size): Читає size (int) байтів/символів з файлу.
  • seek(offset): Переміщується до позиції offset (int) у файлі.
    • Наприклад, await myfile.seek(0) поверне курсор на початок файлу.
    • This is especially useful if you run await myfile.read() once and then need to read the contents again. Це особливо корисно, якщо Ви виконуєте await await myfile.read() один раз, а потім потрібно знову прочитати вміст.
  • close(): Закриває файл.

Оскільки всі ці методи є асинхронними async, Вам потрібно використовувати "await":

Наприклад, всередині async функції обробки шляху Ви можете отримати вміст за допомогою:

contents = await myfile.read()

Якщо Ви знаходитесь у звичайній def функції обробки шляху, Ви можете отримати доступ до UploadFile.file безпосередньо, наприклад:

contents = myfile.file.read()

/// note | Технічні деталі async

Коли Ви використовуєте async методи, FastAPI виконує файлові операції у пулі потоків та очікує їх завершення.

///

/// note | Технічні деталі Starlette

UploadFile у FastAPI успадковується безпосередньо від UploadFile у Starlette, але додає деякі необхідні частини, щоб зробити його сумісним із Pydantic та іншими компонентами FastAPI.

///

Що таке "Form Data"

Спосіб, у який HTML-форми (<form></form>) надсилають дані на сервер, зазвичай використовує "спеціальне" кодування, відмінне від JSON.

FastAPI забезпечує правильне зчитування цих даних з відповідної частини запиту, а не з JSON.

/// note | Технічні деталі

Дані з форм зазвичай кодуються за допомогою "media type" application/x-www-form-urlencoded, якщо вони не містять файлів.

Але якщо форма містить файли, вона кодується у форматі multipart/form-data. Якщо Ви використовуєте File, FastAPI визначить, що потрібно отримати файли з відповідної частини тіла запиту.

Щоб дізнатися більше про ці типи кодування та формові поля, ознайомтеся з документацією MDN щодо POST.

///

/// warning | Увага

Ви можете оголосити кілька параметрів File і Form в операції шляху, але Ви не можете одночасно оголошувати поля Body, які мають надходити у форматі JSON, оскільки тіло запиту буде закодоване у форматі multipart/form-data, а не application/json.

Це не обмеження FastAPI, а особливість протоколу HTTP.

///

Опціональне Завантаження Файлів

Файл можна зробити необов’язковим, використовуючи стандартні анотації типів і встановлюючи значення за замовчуванням None:

{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}

UploadFile із Додатковими Мета Даними

Ви також можете використовувати File() разом із UploadFile, наприклад, для встановлення додаткових метаданих:

{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}

Завантаження Кількох Файлів

Можна завантажувати кілька файлів одночасно.

Вони будуть пов’язані з одним і тим самим "form field", який передається у вигляді "form data".

Щоб це реалізувати, потрібно оголосити список bytes або UploadFile:

{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}

Ви отримаєте, як і було оголошено, list із bytes або UploadFile.

/// note | Технічні деталі

Ви також можете використати from starlette.responses import HTMLResponse.

FastAPI надає ті ж самі starlette.responses, що й fastapi.responses, для зручності розробників. Однак більшість доступних відповідей надходять безпосередньо від Starlette.

///

Завантаження декількох файлів із додатковими метаданими

Так само як і раніше, Ви можете використовувати File(), щоб встановити додаткові параметри навіть для UploadFile:

{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}

Підсумок

Використовуйте File, bytesта UploadFile, щоб оголошувати файли для завантаження у запитах, які надсилаються у вигляді form data.