How do I return an image in fastAPI?

前端 未结 6 1891
灰色年华
灰色年华 2020-12-14 17:51

Using the python module fastAPI, I can\'t figure out how to return an image. In flask I would do something like this:

@app.route(\"/vector_image\", methods=[         


        
相关标签:
6条回答
  • 2020-12-14 18:35

    Thanks to @biophetik's answer, with an important reminder that caused me confusion: If you're using BytesIO especially with PIL/skimage, make sure to also do img.seek(0) before returning!

    @app.get("/generate")
    def generate(data: str):
      img = generate_image(data)
      print('img=%s' % (img.shape,))
      buf = BytesIO()
      imsave(buf, img, format='JPEG', quality=100)
      buf.seek(0) # important here!
      return StreamingResponse(buf, media_type="image/jpeg",
        headers={'Content-Disposition': 'inline; filename="%s.jpg"' %(data,)})
    
    0 讨论(0)
  • 2020-12-14 18:37

    All the other answer(s) is on point, but now it's so easy to return an image

    from fastapi.responses import FileResponse
    
    @app.get("/")
    async def main():
        return FileResponse("your_image.jpeg")
    
    0 讨论(0)
  • 2020-12-14 18:40

    The answer from @SebastiánRamírez pointed me in the right direction, but for those looking to solve the problem, I needed a few lines of code to make it work. I needed to import FileResponse from starlette (not fastAPI?), add CORS support, and return from a temporary file. Perhaps there is a better way, but I couldn't get streaming to work:

    from starlette.responses import FileResponse
    from starlette.middleware.cors import CORSMiddleware
    import tempfile
    
    app = FastAPI()
    app.add_middleware(
        CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]
    )
    
    @app.post("/vector_image")
    def image_endpoint(*, vector):
        # Returns a raw PNG from the document vector (define here)
        img = my_function(vector)
    
        with tempfile.NamedTemporaryFile(mode="w+b", suffix=".png", delete=False) as FOUT:
            FOUT.write(img)
            return FileResponse(FOUT.name, media_type="image/png")
    
    0 讨论(0)
  • 2020-12-14 18:41

    You can do something very similar in FastAPI

    from fastapi import FastAPI, Response
    
    app = FastAPI()
    
    @app.post("/vector_image/")
    async def image_endpoint():
        # img = ... # Create the image here
        return Response(content=img, media_type="image/png")
    
    0 讨论(0)
  • 2020-12-14 18:53

    I had a similar issue but with a cv2 image. This may be useful for others. Uses the StreamingResponse.

    import io
    from starlette.responses import StreamingResponse
    
    app = FastAPI()
    
    @app.post("/vector_image")
    def image_endpoint(*, vector):
        # Returns a cv2 image array from the document vector
        cv2img = my_function(vector)
        res, im_png = cv2.imencode(".png", cv2img)
        return StreamingResponse(io.BytesIO(im_png.tobytes()), media_type="image/png")
    
    0 讨论(0)
  • 2020-12-14 18:57

    It's not properly documented yet, but you can use anything from Starlette.

    So, you can use a FileResponse if it's a file in disk with a path: https://www.starlette.io/responses/#fileresponse

    If it's a file-like object created in your path operation, in the next stable release of Starlette (used internally by FastAPI) you will also be able to return it in a StreamingResponse.

    0 讨论(0)
提交回复
热议问题