Загрузка файлов в FastAPI

FastAPI предоставляетFileиUploadFileДва способа обработки загрузки файлов: поддержка загрузки отдельных файлов и смешанной загрузки форм и файлов.


Установите зависимости

Загрузка файлов также зависит отpython-multipart:

pip install python-multipart

Использование UploadFile

UploadFileявляется рекомендуемым подходом, он предоставляет более богатый интерфейс для доступа к информации о файле:

Пример

from fastapi import FastAPI, UploadFile

app = FastAPI()


@app.post("/uploadfile/")
async def create_upload_file(file: Upload):
    # Свойства и методы, предоставляемые Upload
    return {
        "filename": file.filename,          # Имя файла
        "content_type": file.content_type,  # MIME-тип файла
        "size": file.size,                  # Размер файла (в байтах)
    }

UploadFileСвойства и методы:

Атрибуты/МетодыTypeОписание
filenamestr | NoneИсходное имя загруженного файла
content_typestr | NoneMIME-тип файла (например,image/png)
fileSpooledTemporaryFileФайлоподобный объект, который может читать содержимое файла
sizeint | NoneРазмер файла (в байтах)
read()МетодыЧитать содержимое файла какbytes
write()МетодыЗаписать содержимое в файл
seek()МетодыПереместить позицию указателя файла
close()МетодыЗакрытие файла

UploadFileИспользует "SpooledTemporaryFile" для хранения содержимого файла. Когда файл небольшой, он хранится в памяти; когда файл большой, он автоматически записывается на диск, поэтому это болееbytesБолее экономично по памяти.


Используйте File для получения содержимого файла

FileНепосредственно читать содержимое файла какbytes, подходит для небольших файлов:

Пример

from fastapi import FastAPI, File

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes = File()):
    # file — это необработанные байтовые данные файла
    return {"file_size": len(file)}

FileиUploadFileсравнение:

Пункт сравненияFileUploadFile
Типы данныхbytesОбъект File
Использование памятиЗагрузить весь файл в памятьБольшие файлы автоматически записываются на диск
Информация о файлеНет (только содержимое)Есть имя файла, тип, размер
Применимые сценариинебольшой файлСценарии с большими файлами или когда нужна информация о файле

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

Использовать значение по умолчаниюNoneСделать загрузку файла необязательной:

Пример

from fastapi import FastAPI, UploadFile

app = FastAPI()


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile | None = Отсутствует):
    if not file:
        return {"message": "Файл не загружен"}
    return {"filename": file.filename}

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

Используйте список для получения нескольких файлов:

Пример

from fastapi import FastAPI, UploadFile

app = FastAPI()


@app.post("/uploadfiles/")
async def create_upload_files(files: list[UploadFile]):
    return {"filenames": [file.filename for file in files]}

Смешанная загрузка формы и файла

Вы можете одновременно получать данные формы и файлы в одном маршруте:

Пример

from fastapi import FastAPI, File, UploadFile, Form

app = FastAPI()


@app.post("/items/")
async def create_item(
    # Поля формы
    name: str = Form(...),
    description: str | None = Form(None),
    # Загрузка файла
    file: UploadFile | None = None,
):
    result = {"name": name, "description": description}
    if file:
        result["filename"] = file.filename
    return result

Сохранить загруженный файл

Следующий пример показывает, как сохранять загруженные файлы на диск:

Пример

import shutil
from fastapi import FastAPI, UploadFile

app = FastAPI()


@app.post("/uploadfile/")
async def create_upload_file(file: Upload):
    # Сохранить загруженный файл по указанному пути
    with open(f"uploads/{file.filename}", "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
    return {"filename": file.filename, "message": "Файл успешно загружен"}

В реальных проектах при загрузке файлов обратите внимание: 1) Проверяйте тип и размер файла; 2) Используйте безопасные имена файлов (избегайте атак с обходом пути); 3) Ограничьте права на каталог загрузки; 4) Для больших файлов используйте потоковую передачу вместо чтения всего сразу.


Итог

  • РекомендуетсяUploadFile, это экономит больше памяти и предоставляет расширенную информацию о файле
  • FileПодходит для сценариев с небольшими файлами, читается напрямую какbytes
  • Использованиеlist[UploadFile]Получение нескольких загружаемых файлов
  • form (Form) и file (UploadFile) можно использовать в одном и том же маршруте
  • Обратите внимание на безопасность при загрузке файлов: проверяйте типы файлов, используйте безопасные имена файлов и ограничивайте размеры
Другие расширения