如何让外部API访问大文件?

问题描述 投票:0回答:1

我是 webdev 新手,我有这样的用例:用户向 API 发送一个大文件(例如视频文件),然后该文件需要可供其他 API 访问(这些 API 可能位于不同的 API 上)服务器)以进行进一步处理。

我使用 FastAPI 作为后端,定义一个类型为

UploadFile
的文件参数来接收和存储文件。但是,让其他 API 可以访问此文件的最佳方法是什么?有没有办法从保存的文件中获取可公开访问的
URL
,其他 API 可以用来下载该文件?

python rest fastapi web-development-server
1个回答
6
投票

返回文件响应

首先,要返回从 FastAPI 后端保存在磁盘上的

file
,您可以使用
FileResponse
(如果文件已完全加载到内存中,请参阅此处)。例如:

from fastapi import FastAPI
from fastapi.responses import FileResponse

some_file_path = "large-video-file.mp4"
app = FastAPI()

@app.get("/")
def main():
    return FileResponse(some_file_path)

如果

file
太大而无法装入内存,因为您可能没有足够的内存来处理文件数据,例如,如果您有 16GB RAM,则无法加载 100GB 文件 - 您可以使用
StreamingResponse
。这样,您不必先将其全部读取到内存中,而是将其分块加载到内存中,从而一次处理一个块的数据。下面给出示例。如果您发现使用
yield from f
StreamingResponse
相当慢,您可以创建一个自定义生成器,如此答案中所述。

from fastapi import FastAPI
from fastapi.responses import StreamingResponse

some_file_path = "large-video-file.mp4"
app = FastAPI()

@app.get("/")
def main():
    def iterfile():
        with open(some_file_path, mode="rb") as f:
            yield from f

    return StreamingResponse(iterfile(), media_type="video/mp4")

向公众公开API

至于将您的 API 公开给公众(即外部 API、用户、开发人员等),您可以使用 ngrok(或 expose,如此答案中所建议)。

Ngrok 是一个跨平台应用程序,使开发人员能够以最小的努力将本地“开发服务器”公开到互联网。要将 ngrok 代理嵌入到您的 FastAPI 应用程序中,您可以使用

pyngrok
 — 如 
here
建议(请参阅 here 了解 FastAPI 集成示例)。如果您想通过 Google Colab(使用 ngrok)而不是本地计算机来运行和公开您的 FastAPI 应用程序,请查看
这个答案
(也可以在网络)。 如果您正在寻找更持久的解决方案,您可能需要看看云平台,更具体地说,是平台即服务 (PaaS)。我强烈建议您仔细阅读

FastAPI 的部署文档

。仔细查看关于 HTTPS部署概念 重要提示

通过将您的 API 暴露给外界,您也将其暴露于各种形式的攻击之下。在向公众公开您的 API 之前(即使是免费的),您需要确保提供安全访问(使用

HTTPS

),以及

authentication
(验证用户身份)和
authorisation
(验证他们的访问权限;换句话说,验证用户有权访问哪些特定路由、文件和数据)—查看 1.
OAuth2 和 JWT 令牌
、2. OAuth2 范围、3. 基于角色访问控制 (RBAC),4.获取当前用户如何使用 FastAPI 实现基于角色的访问控制 此外,如果您将 API 公开供公众使用,您可能希望限制 API 的使用,因为计算成本高昂、资源有限、

DDoS 攻击

暴力攻击网页抓取,或只是由于固定数量的请求的每月费用。您可以在应用程序级别使用slowapi(相关帖子此处)来实现这一点,或者在平台级别通过托管服务设置速率限制(如果允许)。此外,您需要确保用户上传的文件具有允许的文件扩展名,例如 .mp4,并且不是具有

.exe
等扩展名的文件,这些文件可能对您的系统有害。最后,您还需要确保上传的文件不超过预定义的
MAX_FILE_SIZE
限制(基于您的需求和系统资源),以便防止经过身份验证的用户或攻击者上传极大的文件,从而导致导致消耗服务器资源,导致应用程序最终崩溃。但是,您不应该依赖
Content-Length
中存在的
request
标头来执行此操作,因为客户端可能很容易更改甚至删除它。您应该使用类似于
这个答案(查看“更新”部分)的方法,该方法使用 request.stream() 在传入数据到达时分块处理它们,而不是首先将整个文件加载到内存中。通过使用简单的计数器,例如 
total_len += len(chunk)
,您可以检查文件大小是否超过
MAX_FILE_SIZE
,如果是,则使用
HTTPException
状态代码引发
HTTP_413_REQUEST_ENTITY_TOO_LARGE
(请参阅
此答案  同样,了解更多详细信息和代码示例)。
阅读有关 Cloudflare 上 FastAPI 的 

安全文档

API 安全 的更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.