# Загрузка файлов Используя класс `File`, мы можем позволить клиентам загружать файлы. /// info | Дополнительная информация Чтобы получать загруженные файлы, сначала установите `python-multipart`. Например: `pip install python-multipart`. Это связано с тем, что загружаемые файлы передаются как данные формы. /// ## Импорт `File` Импортируйте `File` и `UploadFile` из модуля `fastapi`: {* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} ## Определите параметры `File` Создайте параметры `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 `async` интерфейс. * Он предоставляет реальный объект Python `SpooledTemporaryFile` который вы можете передать непосредственно другим библиотекам, которые ожидают файл в качестве объекта. ### `UploadFile` `UploadFile` имеет следующие атрибуты: * `filename`: Строка `str` с исходным именем файла, который был загружен (например, `myimage.jpg`). * `content_type`: Строка `str` с типом содержимого (MIME type / media type) (например, `image/jpeg`). * `file`: `SpooledTemporaryFile` (a file-like объект). Это фактический файл Python, который можно передавать непосредственно другим функциям или библиотекам, ожидающим файл в качестве объекта. `UploadFile` имеет следующие методы `async`. Все они вызывают соответствующие файловые методы (используя внутренний SpooledTemporaryFile). * `write(data)`: Записать данные `data` (`str` или `bytes`) в файл. * `read(size)`: Прочитать количество `size` (`int`) байт/символов из файла. * `seek(offset)`: Перейти к байту на позиции `offset` (`int`) в файле. * Наример, `await myfile.seek(0)` перейдет к началу файла. * Это особенно удобно, если вы один раз выполнили команду `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 **FastAPI** наследует `UploadFile` непосредственно из **Starlette**, но добавляет некоторые детали для совместимости с **Pydantic** и другими частями FastAPI. /// ## Про данные формы ("Form Data") Способ, которым HTML-формы (`
`) отправляют данные на сервер, обычно использует "специальную" кодировку для этих данных, отличную от JSON. **FastAPI** позаботится о том, чтобы считать эти данные из нужного места, а не из JSON. /// note | Технические детали Данные из форм обычно кодируются с использованием "media type" `application/x-www-form-urlencoded` когда он не включает файлы. Но когда форма включает файлы, она кодируется как multipart/form-data. Если вы используете `File`, **FastAPI** будет знать, что ему нужно получить файлы из нужной части тела. Если вы хотите узнать больше об этих кодировках и полях форм, перейдите по ссылке MDN web docs forPOST.
///
/// 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] *}
## Загрузка нескольких файлов
Можно одновременно загружать несколько файлов.
Они будут связаны с одним и тем же "полем формы", отправляемым с помощью данных формы.
Для этого необходимо объявить список `bytes` или `UploadFile`:
{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}
Вы получите, как и было объявлено, список `list` из `bytes` или `UploadFile`.
/// note | Technical Details
Можно также использовать `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` для работы с файлами, которые будут загружаться и передаваться в виде данных формы.