如何在 fastAPI 中返回图像?

2024-01-07

使用Python模块fastAPI https://fastapi.tiangolo.com/,我不知道如何返回图像。在烧瓶中我会做这样的事情:

@app.route("/vector_image", methods=["POST"])
def image_endpoint():
    # img = ... # Create the image here
    return Response(img, mimetype="image/png")

这个模块中对应的调用是什么?


如果内存中已经有图像的字节

返回一个fastapi.responses.Response与您的定制content and media_type.

您还需要修改端点装饰器,以使 FastAPI 将正确的媒体类型放入 OpenAPI 规范中。

@app.get(
    "/image",

    # Set what the media type will be in the autogenerated OpenAPI specification.
    # fastapi.tiangolo.com/advanced/additional-responses/#additional-media-types-for-the-main-response
    responses = {
        200: {
            "content": {"image/png": {}}
        }
    },

    # Prevent FastAPI from adding "application/json" as an additional
    # response media type in the autogenerated OpenAPI specification.
    # https://github.com/tiangolo/fastapi/issues/3258
    response_class=Response
)
def get_image()
    image_bytes: bytes = generate_cat_picture()
    # media_type here sets the media type of the actual response sent to the client.
    return Response(content=image_bytes, media_type="image/png")

See the Response文档 https://fastapi.tiangolo.com/advanced/custom-response/#response.

如果您的图像仅存在于文件系统上

返回一个fastapi.responses.FileResponse.

See the FileResponse文档 https://fastapi.tiangolo.com/advanced/custom-response/#fileresponse.


小心StreamingResponse

其他答案建议StreamingResponse. StreamingResponse很难正确使用,所以我不推荐它,除非你确定你不能使用Response or FileResponse.

特别是,这样的代码毫无意义。它不会以任何有用的方式“流”图像。

@app.get("/image")
def get_image()
    image_bytes: bytes = generate_cat_picture()
    # ❌ Don't do this.
    image_stream = io.BytesIO(image_bytes)
    return StreamingResponse(content=image_stream, media_type="image/png")

首先,StreamingResponse(content=my_iterable)通过迭代提供的块来流my_iterable。但是当那个可迭代对象是BytesIO, 这些块将是\n- 终止线 https://docs.python.org/3.8/library/io.html#io.IOBase,这对于二值图像没有意义。

即使块划分有意义,这里分块也是毫无意义的,因为我们拥有整个image_bytes bytes从一开始就可用的对象。我们不妨将整个事情传递到一个Response从一开始就。通过阻止来自 FastAPI 的数据,我们不会获得任何好处。

Second, StreamingResponse对应于HTTP 分块传输编码 https://en.wikipedia.org/wiki/Chunked_transfer_encoding。 (这可能取决于您的 ASGI 服务器,但情况是这样的Uvicorn https://www.uvicorn.org/至少。)这对于分块传输编码来说并不是一个好的用例。

当您事先不知道输出的大小,并且您不想等到收集所有内容才能在开始将其发送到客户端之前找到答案时,分块传输编码就很有意义。这可以适用于提供慢速数据库查询结果之类的东西,但它通常不适用于提供图像。

不必要的分块传输编码可能是有害的。例如,这意味着客户端在下载文件时无法显示进度条。看:

  • 内容长度标头与分块编码 https://stackoverflow.com/questions/2419281/content-length-header-versus-chunked-encoding
  • 在静态文件上使用 Transfer-Encoding: chunked 是个好主意吗? https://stackoverflow.com/questions/30151746/is-it-a-good-idea-to-use-transfer-encoding-chunked-on-static-files
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 fastAPI 中返回图像? 的相关文章

随机推荐