FastAPI: Как скачивать байты через API

Есть ли способ скачать файл через FastAPI? Нужные нам файлы находятся в Azure Datalake, и их извлечение из озера не является проблемой, проблема возникает, когда мы пытаемся передать байты, которые мы получаем из базы данных, на локальный компьютер.

Мы безуспешно пытались использовать различные модули в FastAPI, такие как starlette.responses.FileResponse и fastapi.Response.

В Flask это не проблема, и это можно сделать следующим образом:

from io import BytesIO
from flask import Flask
from werkzeug import FileWrapper

flask_app = Flask(__name__)

@flask_app.route('/downloadfile/<file_name>', methods=['GET'])
def get_the_file(file_name: str):
    the_file = FileWrapper(BytesIO(download_file_from_directory(file_name)))
    if the_file:
        return Response(the_file, mimetype=file_name, direct_passthrough=True)

При запуске с допустимым именем файла файл автоматически загружается. Есть ли аналогичный способ в FastAPI?

Решено

После некоторого устранения неполадок я нашел способ сделать это.

from fastapi import APIRouter, Response

router = APIRouter()

@router.get('/downloadfile/{file_name}', tags=['getSkynetDL'])
async def get_the_file(file_name: str):
    # the_file object is raw bytes
    the_file = download_file_from_directory(file_name)
    if the_file:
        return Response(the_file)

Итак, после долгих поисков неисправностей и часов просмотра документации, это было все, что потребовалось, просто вернуть байты как Response(the_file).


person Markus    schedule 14.09.2020    source источник
comment
Вы должны указать его как ответ ниже и отметить его как правильный ответ, чтобы закрыть этот вопрос.   -  person Sami Al-Subhi    schedule 07.02.2021


Ответы (2)


Насколько я знаю, вам нужно установить media_type в соответствующий тип. Я сделал это с некоторым кодом год назад, и он работал нормально.

@app.get("/img/{name}")
def read(name: str, access_token_cookie: str=Cookie(None)):
  r = internal.get_data(name)
  if r is None:
    return RedirectResponse(url="/static/default.png")
  else:
    return Response(content=r["data"], media_type=r["mime"])

r - это словарь с data как необработанными байтами и mime типом данных, заданным PythonMagick.

person Matthieu Brucher    schedule 14.09.2020

После некоторого устранения неполадок я нашел способ сделать это.

from fastapi import APIRouter, Response

router = APIRouter()

@router.get('/downloadfile/{file_name}', tags=['getSkynetDL'])
async def get_the_file(file_name: str):
    # the_file object is raw bytes
    the_file = download_file_from_directory(file_name)
    if the_file:
        return Response(the_file)

Итак, после долгого устранения неполадок и часов просмотра документации, это было все, что потребовалось, просто вернуть байты как Response(the_file) без дополнительных параметров и без дополнительного форматирования для необработанного байтового объекта.

person Markus    schedule 14.09.2020