FastAPI如何返回文件字节流?并且附带一些json参数

文章目录

  • [GET方法 StreamingResponse](#GET方法 StreamingResponse)
  • [POST方法 StreamingResponse](#POST方法 StreamingResponse)
  • 其他
  • 关于压缩

GET方法 StreamingResponse

服务器:

clike 复制代码
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from starlette.responses import FileResponse
from pydantic import BaseModel

app = FastAPI()


# 创建一个 Base 模型,用于表示其他的 JSON 信息
class AdditionalInfo(BaseModel):
    message: str
    status: str


@app.get("/get_demo_image_with_json")
async def get_demo_image_with_json():
    # 从文件中读取字节流
    file_path = "face.png"
    file_like = open(file_path, mode="rb")

    # 模拟其他的 JSON 信息
    json_info = AdditionalInfo(message="Image loaded successfully", status="OK")

    # 使用 StreamingResponse 返回字节流和其他的 JSON 信息
    return StreamingResponse(file_like, media_type="image/jpeg",
                             headers={"Additional-Info": json_info.model_dump_json()})


if __name__ == '__main__':
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8000)

客户端:

clike 复制代码
import requests

url = "http://127.0.0.1:8000/get_demo_image_with_json"

response = requests.get(url)

# 检查请求是否成功
if response.status_code == 200:
    # 获取文件的字节流
    image_data = response.content

    # 处理其他的 JSON 信息
    additional_info = response.headers.get("Additional-Info")

    # 在此处添加您的处理逻辑,例如保存字节流到文件,解析 JSON 信息等
    # ...

    print("Image loaded successfully.")
    print(f"Additional Info: {additional_info}")

else:
    print(f"Failed to fetch image. Status code: {response.status_code}")

POST方法 StreamingResponse

服务器代码:

clike 复制代码
import io

from fastapi import FastAPI, File, UploadFile
from fastapi.responses import StreamingResponse
from pydantic import BaseModel

app = FastAPI()


# 创建一个 Base 模型,用于表示其他的 JSON 信息
class AdditionalInfo(BaseModel):
    message: str
    status: str


@app.post("/get_demo_image_with_json")
async def get_demo_image_with_json():
    #  读取face.png
    image_data = open("face.png", "rb").read()

    # 模拟其他的 JSON 信息
    json_info = AdditionalInfo(message="Image loaded successfully", status="OK")

    # 使用 StreamingResponse 返回字节流和其他的 JSON 信息
    return StreamingResponse(io.BytesIO(image_data), media_type="image/png",
                             headers={"Additional-Info": json_info.model_dump_json()})


if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

客户端参数:

clike 复制代码
import requests

url = "http://127.0.0.1:8000/get_demo_image_with_json"

response = requests.post(url)

# 检查请求是否成功
if response.status_code == 200:
    # 获取文件的字节流
    image_data = response.content
    # 写入文件
    with open("demo_image_with_json.png", "wb") as fp:
        fp.write(image_data)
    # 打印其他参数
    print(response.headers["Additional-Info"])

else:
    print(f"Failed to fetch image. Status code: {response.status_code}")

其他

还有FileResponse、base64。

FileResponse太肤浅,base64对于大文件来说太大。

在 FastAPI 中,返回文件字节流的主要方式包括使用 StreamingResponseFileResponse。这两者都可以用于返回二进制数据,例如图像文件。

  1. StreamingResponse: 适用于以流式方式发送数据,对于大型文件特别有用,因为它允许在数据生成时就开始发送,而不必等到整个数据集都可用。

    python 复制代码
    from fastapi.responses import StreamingResponse
    
    @app.get("/get_demo_image")
    async def get_demo_image():
        image_data = open("face.png", "rb").read()
        return StreamingResponse(io.BytesIO(image_data), media_type="image/png")
  2. FileResponse: 适用于返回文件,可以从文件系统路径中读取文件内容,也可以通过 content 参数直接传递文件内容。

    python 复制代码
    from fastapi.responses import FileResponse
    
    @app.get("/get_demo_image")
    async def get_demo_image():
        image_data = open("face.png", "rb").read()
        return FileResponse(content=image_data, media_type="image/png")

这两种方法都是有效的,并且具体的选择可能取决于你的应用程序的需求和性能考虑。如果你希望以异步方式发送文件,你可能会更喜欢 StreamingResponse。如果你只是从文件系统中返回文件,FileResponse 是一个更简单的选择。

关于压缩

clike 复制代码
FastAPI本身没有直接支持响应内容压缩的中间件,但你可以通过使用 Starlette 的中间件来实现这一功能。具体来说,Starlette 提供了 `Middleware` 类,你可以使用它来定义自定义中间件。以下是一个简单的例子,演示如何使用 Gzip 中间件来压缩响应内容:

```python
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from starlette.responses import FileResponse
from starlette.middleware.gzip import GZipMiddleware
from pydantic import BaseModel

app = FastAPI()

# 使用 Gzip 中间件
app.add_middleware(GZipMiddleware, minimum_size=1000, compress_level=6)

# 创建一个 Base 模型,用于表示其他的 JSON 信息
class AdditionalInfo(BaseModel):
    message: str
    status: str

@app.get("/get_demo_image_with_json")
async def get_demo_image_with_json():
    # 从文件中读取字节流
    file_path = "face.png"
    file_like = open(file_path, mode="rb")

    # 模拟其他的 JSON 信息
    json_info = AdditionalInfo(message="Image loaded successfully", status="OK")

    # 使用 StreamingResponse 返回字节流和其他的 JSON 信息
    return StreamingResponse(file_like, media_type="image/jpeg",
                             headers={"Additional-Info": json_info.json()})

在上述代码中,通过添加 GZipMiddleware 到 FastAPI 应用中,你启用了 Gzip 压缩。在 StreamingResponse 中返回的字节流会在传输过程中被压缩。请注意,Gzip 压缩可能会增加 CPU 使用,但通常可以显著减小传输的数据量,提高性能。你可以根据需求调整 minimum_sizecompress_level 参数。

相关推荐
Wang's Blog23 分钟前
Java 接入Redis: 通用命令与键管理
java·服务器·redis
Wang's Blog25 分钟前
Java 接入Redis: 列表集合与有序集合操作命令
java·服务器·redis
Ivanqhz1 小时前
SVD++算法
java·服务器·网络·深度学习·神经网络
qq_2518364572 小时前
springboot vue3 开发实现 拼豆管理系统
java·开发语言·ai编程
caoerzhong2 小时前
JeeWMS 开源仓库管理系统全景解读:一套 Java WMS 如何把 WMS/OMS/BMS/TMS 装进同一个系统
java·开源
曹牧2 小时前
Java集合框架:List、ArrayList、Map 和 HashMap
java
顾城猿2 小时前
STOMP 协议
java
basketball6163 小时前
Python FastAPI 介绍以及常用方法
python·fastapi·vllm·ai infra
+VX:Fegn08953 小时前
计算机毕业设计|基于springboot + vue旅游管理系统(源码+数据库+文档)
java·开发语言·vue.js·spring boot·课程设计
需要8263 小时前
MySQL 索引 B+ 树与“查询为什么变慢了
java·spring boot·spring·spring cloud·tomcat