File - это класс, который наследуется непосредственно от Form.
Но помните, что когда вы импортируете Query, Path, File и другие из fastapi, на самом деле это функции, которые возвращают специальные классы.
Подсказка
Для объявления тела файла необходимо использовать File, поскольку в противном случае параметры будут интерпретироваться как параметры запроса или параметры тела (JSON).
Файлы будут загружены как данные формы.
Если вы объявите тип параметра у функции операции пути как bytes, то FastAPI прочитает файл за вас, и вы получите его содержимое в виде bytes.
Следует иметь в виду, что все содержимое будет храниться в памяти. Это хорошо подходит для небольших файлов.
Однако возможны случаи, когда использование UploadFile может оказаться полезным.
Использование UploadFile имеет ряд преимуществ перед bytes:
Использовать File() в значении параметра по умолчанию не обязательно.
При этом используется "буферный" файл:
Файл, хранящийся в памяти до максимального предела размера, после преодоления которого он будет храниться на диске.
Это означает, что он будет хорошо работать с большими файлами, такими как изображения, видео, большие бинарные файлы и т.д., не потребляя при этом всю память.
Он предоставляет реальный объект Python SpooledTemporaryFile который вы можете передать непосредственно другим библиотекам, которые ожидают файл в качестве объекта.
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функции операции пути можно получить содержимое с помощью:
contents=awaitmyfile.read()
Если вы находитесь внутри обычной defфункции операции пути, можно получить прямой доступ к файлу UploadFile.file, например:
contents=myfile.file.read()
Технические детали async
При использовании методов asyncFastAPI запускает файловые методы в пуле потоков и ожидает их.
Технические детали Starlette
FastAPI наследует UploadFile непосредственно из Starlette, но добавляет некоторые детали для совместимости с Pydantic и другими частями FastAPI.
Способ, которым HTML-формы (<form></form>) отправляют данные на сервер, обычно использует "специальную" кодировку для этих данных, отличную от JSON.
FastAPI позаботится о том, чтобы считать эти данные из нужного места, а не из JSON.
Технические детали
Данные из форм обычно кодируются с использованием "media type" application/x-www-form-urlencoded когда он не включает файлы.
Но когда форма включает файлы, она кодируется как multipart/form-data. Если вы используете File, FastAPI будет знать, что ему нужно получить файлы из нужной части тела.
Если вы хотите узнать больше об этих кодировках и полях форм, перейдите по ссылке MDN web docs for POST.
Внимание
В операции функции операции пути можно объявить несколько параметров File и Form, но нельзя также объявлять поля Body, которые предполагается получить в виде JSON, поскольку тело запроса будет закодировано с помощью multipart/form-data, а не application/json.
Это не является ограничением FastAPI, это часть протокола HTTP.
Вы также можете использовать File() вместе с UploadFile, например, для установки дополнительных метаданных:
fromtypingimportAnnotatedfromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File(description="A file read as bytes")]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:Annotated[UploadFile,File(description="A file read as UploadFile")],):return{"filename":file.filename}
fromfastapiimportFastAPI,File,UploadFilefromtyping_extensionsimportAnnotatedapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File(description="A file read as bytes")]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:Annotated[UploadFile,File(description="A file read as UploadFile")],):return{"filename":file.filename}
Подсказка
Предпочтительнее использовать версию с аннотацией, если это возможно.
fromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:bytes=File(description="A file read as bytes")):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile=File(description="A file read as UploadFile"),):return{"filename":file.filename}
Вы получите, как и было объявлено, список list из bytes или UploadFile.
Technical Details
Можно также использовать from starlette.responses import HTMLResponse.
FastAPI предоставляет тот же starlette.responses, что и fastapi.responses, просто для удобства разработчика. Однако большинство доступных ответов поступает непосредственно из Starlette.
Загрузка нескольких файлов с дополнительными метаданными¶
Так же, как и раньше, вы можете использовать File() для задания дополнительных параметров, даже для UploadFile: