committed by
GitHub
1 changed files with 175 additions and 0 deletions
@ -0,0 +1,175 @@ |
|||
# Запит файлів |
|||
|
|||
Ви можете визначити файли, які будуть завантажуватися клієнтом, використовуючи `File`. |
|||
|
|||
/// info | Інформація |
|||
|
|||
Щоб отримувати завантажені файли, спочатку встановіть <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">python-multipart</a>. |
|||
|
|||
Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його та встановили пакет, наприклад: |
|||
|
|||
```console |
|||
$ 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()` у значенні за замовчуванням параметра. |
|||
* Використовується "буферизований" файл: |
|||
* Файл зберігається в пам'яті до досягнення певного обмеження, після чого він записується на диск. |
|||
* Це означає, що він добре працює для великих файлів, таких як зображення, відео, великі двійкові файли тощо, не споживаючи всю пам'ять. |
|||
Ви можете отримати метадані про завантажений файл. |
|||
* Він має <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> `асинхронний файловий інтерфейс` interface. |
|||
* Він надає фактичний об'єкт Python <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a>, який можна передавати безпосередньо іншим бібліотекам. |
|||
|
|||
### `UploadFile` |
|||
|
|||
`UploadFile` має такі атрибути: |
|||
|
|||
* `filename`: Рядок `str` з оригінальною назвою файлу, який був завантажений (наприклад, `myimage.jpg`). |
|||
* `content_type`: Рядок `str` з MIME-типом (наприклад, `image/jpeg`). |
|||
* `file`: Об'єкт <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">SpooledTemporaryFile</a> (<a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">файлоподібний</a> об'єкт). Це фактичний файловий об'єкт 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` *функції обробки шляху* Ви можете отримати вміст за допомогою: |
|||
|
|||
```Python |
|||
contents = await myfile.read() |
|||
``` |
|||
Якщо Ви знаходитесь у звичайній `def` *функції обробки шляху*, Ви можете отримати доступ до `UploadFile.file` безпосередньо, наприклад: |
|||
|
|||
```Python |
|||
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** визначить, що потрібно отримати файли з відповідної частини тіла запиту. |
|||
|
|||
Щоб дізнатися більше про ці типи кодування та формові поля, ознайомтеся з <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">документацією MDN</abbr> щодо <code>POST</code></a>. |
|||
|
|||
/// |
|||
|
|||
/// 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. |
Loading…
Reference in new issue