FastAPI:如何通过API下载字节流

5
有没有一种通过FastAPI下载文件的方法?我们需要的文件位于Azure Datalake中,从湖中检索它们不是问题,但问题发生在我们尝试将从数据湖获取的字节下载到本地机器时。
我们已尝试使用FastAPI中的不同模块,如starlette.responses.FileResponsefastapi.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)返回即可。


1
将以下与编程有关的内容从英语翻译成中文。请只返回翻译后的文本,不要进行解释。您应该将其作为答案放在下面,并将其标记为正确答案以关闭此问题。 - Sami Al-Subhi
这里的解决方案似乎没有涵盖设置自定义文件名,不过我想可以通过修改路径来使其看起来像是客户端的文件名。 - Nikhil VJ
2
相关答案可以在这里找到:这里这里这里,以及这里这里这里 - Chris
这个回答解决了你的问题吗?如何使用FastAPI从内存缓冲区返回PDF文件? - Chris
"download_file_from_directory"是什么鬼东西? - Shayne
“download_from_directory”只是一个函数,用于从Azure存储容器中检索文件的二进制数据。其中重要的部分是它以字节形式返回文件。 - Markus
3个回答

2

经过进一步的故障排除,我找到了一种方法来实现这个。

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),不需要额外的参数和格式化原始字节对象。

0

如果您想在@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)

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接