11

我正在使用 FastAPI 接收图像,对其进行处理,然后将图像作为 FileResponse 返回。

但是返回的文件是临时文件,端点返回后需要删除。

@app.post("/send")
async def send(imagem_base64: str = Form(...)):

    # Convert to a Pillow image
    image = base64_to_image(imagem_base64)

    temp_file = tempfile.mkstemp(suffix = '.jpeg')
    image.save(temp_file, dpi=(600, 600), format='JPEG', subsampling=0, quality=85)

    return FileResponse(temp_file)

    # I need to remove my file after return it
    os.remove(temp_file)

退回后如何删除文件?

4

4 回答 4

16

您可以在后台任务中删除文件,因为它会在发送响应后运行。

import os
import tempfile

from fastapi import FastAPI
from fastapi.responses import FileResponse

from starlette.background import BackgroundTasks

app = FastAPI()


def remove_file(path: str) -> None:
    os.unlink(path)


@app.post("/send")
async def send(background_tasks: BackgroundTasks):
    fd, path = tempfile.mkstemp(suffix='.txt')
    with os.fdopen(fd, 'w') as f:
        f.write('TEST\n')
    background_tasks.add_task(remove_file, path)
    return FileResponse(path)

另一种方法是将依赖项与 yield一起使用。块代码将finally在响应发送后,甚至在所有后台任务完成后执行。

import os
import tempfile

from fastapi import FastAPI, Depends
from fastapi.responses import FileResponse


app = FastAPI()


def create_temp_file():
    fd, path = tempfile.mkstemp(suffix='.txt')
    with os.fdopen(fd, 'w') as f:
        f.write('TEST\n')
    try:
        yield path
    finally:
        os.unlink(path)


@app.post("/send")
async def send(file_path=Depends(create_temp_file)):
    return FileResponse(file_path)

注意mkstemp()返回一个带有文件描述符和路径的元组。

于 2020-11-06T15:10:23.680 回答
2

您可以将清理任务作为参数传递FileResponse

from starlette.background import BackgroundTask

# ...

def cleanup():
    os.remove(temp_file)

return FileResponse(
    temp_file,
    background=BackgroundTask(cleanup),
)
于 2021-07-29T16:16:34.317 回答
0

建议发送FileResponse附带删除文件或文件夹的后台任务。

点击这里了解更多信息

后台任务将在响应提供后运行,因此它可以安全地删除文件/文件夹。

# ... other important imports
from starlette.background import BackgroundTasks

@app.post("/send")
async def send(imagem_base64: str = Form(...), bg_tasks: BackgroundTasks):

    # Convert to a Pillow image
    image = base64_to_image(imagem_base64)

    temp_file = tempfile.mkstemp(suffix = '.jpeg')
    image.save(temp_file, dpi=(600, 600), format='JPEG', subsampling=0, quality=85)


    bg_tasks.add_task(os.remove, temp_file)
 
   return FileResponse(
    temp_file,
    background=bg_tasks
   )    
于 2021-10-27T13:51:24.753 回答
-1

在您的情况下,返回 aStreamingResponse将是一个更好的选择,并且内存效率更高,因为文件操作将阻止事件循环的整个执行。

由于您接收的数据为b64encoded. 您可以将其读取为一个字节并StreamingResponse从中返回一个。

from fastapi.responses import StreamingResponse
from io import BytesIO

@app.post("/send")
async def send(imagem_base64: str = Form(...)):
    in_memory_file = BytesIO()
    image = base64_to_image(imagem_base64)
    image.save(in_memory_file, dpi=(600, 600), format='JPEG', subsampling=0, quality=85)
    in_memory_file.seek(0)
    return StreamingResponse(in_memory_file.read(), media_type="image/jpeg")
于 2020-11-06T15:12:28.570 回答