Python fastapi загрузка файла

Request Files

Вы можете определить файлы для загрузки клиентом с помощью File .

Чтобы получать загруженные файлы, сначала установите python-multipart .

Например, pip install python-multipart .

Это связано с тем, что загруженные файлы отправляются как «данные формы».

Import File

Импорт File и UploadFile из fastapi :

from fastapi import FastAPI, File, UploadFile app = FastAPI() @app.post("/files/") async def create_file(file: bytes = File( )): return "file_size": len(file)> @app.post("/uploadfile/") async def create_upload_file(file: UploadFile): return "filename": file.filename>

Определить параметры File

Создайте параметры файла так же, как для Body или Form :

from fastapi import FastAPI, File, UploadFile app = FastAPI() @app.post("/files/") async def create_file(file: bytes = File( )): return "file_size": len(file)> @app.post("/uploadfile/") async def create_upload_file(file: UploadFile): return "filename": file.filename>

File — это класс, который наследуется непосредственно от Form .

Но помните, что когда вы импортируете Query , Path , File и другие из fastapi , это на самом деле функции, которые возвращают специальные классы.

Чтобы объявить тела файлов, вам нужно использовать File , потому что в противном случае параметры будут интерпретироваться как параметры запроса или параметры тела (JSON).

Файлы будут загружены как «данные формы».

Если вы объявите тип параметра функции операции пути как bytes , FastAPI прочитает файл для вас, и вы получите содержимое в виде bytes .

Имейте в виду, что это означает, что все содержимое будет сохранено в памяти. Это будет хорошо работать для небольших файлов.

Но есть несколько случаев, когда вы можете извлечь выгоду из использования UploadFile .

Параметры файла с UploadFile

Определите параметр файла с типом UploadFile :

from fastapi import FastAPI, File, UploadFile app = FastAPI() @app.post("/files/") async def create_file(file: bytes = File( )): return "file_size": len(file)> @app.post("/uploadfile/") async def create_upload_file(file: UploadFile): return "filename": file.filename>

Использование UploadFile имеет несколько преимуществ перед bytes :

  • Вам не нужно использовать File() в значении параметра по умолчанию.
  • Он использует «буферный» файл:
    • Файл хранится в памяти до максимального размера, а после превышения этого ограничения будет храниться на диске.

    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) перейдет к началу файла.
      • Это особенно полезно, если вы запускаете await myfile.read() один раз, а затем вам нужно снова прочитать содержимое.

      Поскольку все эти методы являются async , вам нужно «ждать» их.

      Например, внутри функции операции async пути вы можете получить содержимое с помощью:

      contents = await myfile.read()

      Если вы находитесь внутри обычной функции операции def пути , вы можете получить прямой доступ к UploadFile.file , например:

      Когда вы используете async методы, FastAPI запускает файловые методы в пуле потоков и ожидает их.

      Технические детали Starlette

      UploadFile FastAPI напрямую наследуется от UploadFile Starlette , но добавляет некоторые необходимые части, чтобы сделать его совместимым с UploadFile UploadFile другими частями FastAPI.

      Что такое «данные формы»

      Способ, которым HTML-формы ( ) отправляют данные на сервер, обычно использует «специальную» кодировку для этих данных, она отличается от JSON.

      FastAPI обязательно прочитает эти данные из нужного места, а не из JSON.

      Данные из форм обычно кодируются с использованием application/x-www-form-urlencoded «типа мультимедиа» , если они не включают файлы.

      Но когда форма включает файлы, она кодируется как multipart/form-data . Если вы используете File , FastAPI будет знать, что он должен получить файлы из правильной части тела.

      Если вы хотите узнать больше об этих кодировках и полях формы, перейдите к веб-документам MDN для POST .

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

      Это не ограничение FastAPI , это часть протокола HTTP.

      Необязательная загрузка файла

      Вы можете сделать файл необязательным, используя аннотации стандартного типа и установив значение по умолчанию None :

      from typing import Union from fastapi import FastAPI, File, UploadFile app = FastAPI() @app.post("/files/") async def create_file(file: Union[bytes, None] = File(default=None)): if not file: return "message": "No file sent"> else: return "file_size": len(file)> @app.post("/uploadfile/") async def create_upload_file(file: Union[UploadFile, None] = None): if not file: return "message": "No upload file sent"> else: return "filename": file.filename>
      from fastapi import FastAPI, File, UploadFile app = FastAPI() @app.post("/files/") async def create_file(file: bytes | None = File(default=None)): if not file: return "message": "No file sent"> else: return "file_size": len(file)> @app.post("/uploadfile/") async def create_upload_file(file: UploadFile | None = None): if not file: return "message": "No upload file sent"> else: return "filename": file.filename>

      UploadFile с дополнительными метаданными

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

      from fastapi import FastAPI, File, UploadFile app = FastAPI() @app.post("/files/") async def create_file(file: bytes = File(description="A file read as bytes")): return "file_size": len(file)> @app.post("/uploadfile/") async def create_upload_file( file: UploadFile = File(description="A file read as UploadFile"), ): return "filename": file.filename>

      Загрузка нескольких файлов

      Возможна загрузка нескольких файлов одновременно.

      Они будут связаны с одним и тем же «полем формы», отправленным с использованием «данных формы».

      Чтобы использовать это, объявите список bytes или UploadFile :

      from typing import List from fastapi import FastAPI, File, UploadFile from fastapi.responses import HTMLResponse app = FastAPI() @app.post("/files/") async def create_files(files: List[bytes] = File( )): return "file_sizes": [len(file) for file in files]> @app.post("/uploadfiles/") async def create_upload_files(files: List[UploadFile]): return "filenames": [file.filename for file in files]> @app.get("/") async def main(): content = """    """ return HTMLResponse(content=content)
      from fastapi import FastAPI, File, UploadFile from fastapi.responses import HTMLResponse app = FastAPI() @app.post("/files/") async def create_files(files: list[bytes] = File( )): return "file_sizes": [len(file) for file in files]> @app.post("/uploadfiles/") async def create_upload_files(files: list[UploadFile]): return "filenames": [file.filename for file in files]> @app.get("/") async def main(): content = """    """ return HTMLResponse(content=content)

      Вы получите, как объявлено, list байтов или bytes UploadFile .

      Вы также можете использовать from starlette.responses import HTMLResponse .

      FastAPI предоставляет те же starlette.responses , что и fastapi.responses , только для удобства вас, разработчика. Но большинство доступных ответов исходит непосредственно от Старлетт.

      Загрузка нескольких файлов с дополнительными метаданными

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

      from typing import List from fastapi import FastAPI, File, UploadFile from fastapi.responses import HTMLResponse app = FastAPI() @app.post("/files/") async def create_files( files: List[bytes] = File(description="Multiple files as bytes"), ): return "file_sizes": [len(file) for file in files]> @app.post("/uploadfiles/") async def create_upload_files( files: List[UploadFile] = File(description="Multiple files as UploadFile"), ): return "filenames": [file.filename for file in files]> @app.get("/") async def main(): content = """    """ return HTMLResponse(content=content)
      from fastapi import FastAPI, File, UploadFile from fastapi.responses import HTMLResponse app = FastAPI() @app.post("/files/") async def create_files( files: list[bytes] = File(description="Multiple files as bytes"), ): return "file_sizes": [len(file) for file in files]> @app.post("/uploadfiles/") async def create_upload_files( files: list[UploadFile] = File(description="Multiple files as UploadFile"), ): return "filenames": [file.filename for file in files]> @app.get("/") async def main(): content = """    """ return HTMLResponse(content=content)

      Recap

      Используйте File , bytes и UploadFile для объявления файлов, которые будут загружены в запросе, отправленном как данные формы.

      Источник

      Request Forms and Files¶

      You can define files and form fields at the same time using File and Form .

      To receive uploaded files and/or form data, first install python-multipart .

      E.g. pip install python-multipart .

      Import File and Form ¶

      from typing import Annotated from fastapi import FastAPI, File, Form, UploadFile  app = FastAPI() @app.post("/files/") async def create_file( file: Annotated[bytes, File()], fileb: Annotated[UploadFile, File()], token: Annotated[str, Form()], ): return  "file_size": len(file), "token": token, "fileb_content_type": fileb.content_type, > 
      from fastapi import FastAPI, File, Form, UploadFile from typing_extensions import Annotated app = FastAPI() @app.post("/files/") async def create_file( file: Annotated[bytes, File()], fileb: Annotated[UploadFile, File()], token: Annotated[str, Form()], ): return  "file_size": len(file), "token": token, "fileb_content_type": fileb.content_type, > 

      Prefer to use the Annotated version if possible.

      from fastapi import FastAPI, File, Form, UploadFile  app = FastAPI() @app.post("/files/") async def create_file( file: bytes = File(), fileb: UploadFile = File(), token: str = Form() ): return  "file_size": len(file), "token": token, "fileb_content_type": fileb.content_type, > 

      Define File and Form parameters¶

      Create file and form parameters the same way you would for Body or Query :

      from typing import Annotated from fastapi import FastAPI, File, Form, UploadFile app = FastAPI() @app.post("/files/") async def create_file( file: Annotated[bytes, File()],  fileb: Annotated[UploadFile, File()],  token: Annotated[str, Form()], ): return  "file_size": len(file), "token": token, "fileb_content_type": fileb.content_type, > 
      from fastapi import FastAPI, File, Form, UploadFile from typing_extensions import Annotated app = FastAPI() @app.post("/files/") async def create_file( file: Annotated[bytes, File()],  fileb: Annotated[UploadFile, File()],  token: Annotated[str, Form()], ): return  "file_size": len(file), "token": token, "fileb_content_type": fileb.content_type, > 

      Prefer to use the Annotated version if possible.

      from fastapi import FastAPI, File, Form, UploadFile app = FastAPI() @app.post("/files/") async def create_file( file: bytes = File(), fileb: UploadFile = File(), token: str = Form() ): return  "file_size": len(file), "token": token, "fileb_content_type": fileb.content_type, > 

      The files and form fields will be uploaded as form data and you will receive the files and form fields.

      And you can declare some of the files as bytes and some as UploadFile .

      You can declare multiple File and Form parameters in a path operation, but you can’t also declare Body fields that you expect to receive as JSON, as the request will have the body encoded using multipart/form-data instead of application/json .

      This is not a limitation of FastAPI, it’s part of the HTTP protocol.

      Recap¶

      Use File and Form together when you need to receive data and files in the same request.

      Источник

      Читайте также:  Сессии и post php
Оцените статью