如何在`return FileResponse(file_path)`后删除文件

Kle*_*ios 6 python python-asyncio starlette fastapi

我正在使用 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)

Run Code Online (Sandbox Code Playgroud)

返回后如何删除文件?

mad*_*ox2 15

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

from starlette.background import BackgroundTask

# ...

def cleanup():
    os.remove(temp_file)

return FileResponse(
    temp_file,
    background=BackgroundTask(cleanup),
)
Run Code Online (Sandbox Code Playgroud)

更新 12-08-2022

如果有人动态生成文件名,则可以将参数传递给后台任务,例如,如下所示

return FileResponse(
    temp_file,
    background=BackgroundTask(cleanup, file_path),
)
Run Code Online (Sandbox Code Playgroud)

然后,该cleanup函数需要调整为接受一个参数,该参数将是文件名,并使用os.remove文件名作为参数而不是全局变量来调用该函数

  • 更简单:您可以使用“background=BackgroundTask(os.remove, temp_file)”。`os.remove` 已经是一个可调用函数,您可以传递给BackgroundTask,您不需要将其包装到另一个函数中。 (3认同)

ale*_*ame 10

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

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)
Run Code Online (Sandbox Code Playgroud)

另一种方法是对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)
Run Code Online (Sandbox Code Playgroud)

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