FastAPI:如何通过API下载字节



有没有办法通过FastAPI下载文件?我们想要的文件位于Azure Datalake中,从该lake中检索这些文件不是问题,当我们试图将从数据仓库获得的字节降到本地机器时,就会出现问题。

我们尝试在FastAPI中使用不同的模块,如starlette.responses.FileResponsefastapi.Response,但没有成功。

在烧瓶中,这不是一个问题,可以通过以下方式进行:

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)即可。

经过更多的故障排除,我找到了一种方法。

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),而不需要额外的参数,也不需要为原始字节对象设置额外的格式。

据我所知,您需要将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给出的数据类型。

要在@Markus的答案中添加自定义文件名,以防您的api路径没有以整洁的文件名结束,或者您想从服务器端确定自定义文件名并提供给用户:

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)
filename1 = make_filename(file_name) # a custom filename
headers1 = {'Content-Disposition': f'attachment; filename="{filename1}"'}
if the_file:
return Response(the_file, headers=headers1)

最新更新