如何在 `return FileResponse(file_path)` 后删除文件
How to delete the file after a `return FileResponse(file_path)`
我正在使用 FastAPI 接收图像,对其进行处理,然后return将图像作为 FileResponse。
但是 returned 文件是一个临时文件,需要在端点 return 之后删除。
@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)
如何删除 return 之后的文件?
您可以删除 background task 中的文件,因为它会在 运行 发送响应后 。
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)
另一种方法是使用dependency with 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() returns 一个包含文件描述符和路径的元组。
返回 StreamingResponse
在您的情况下会是更好的选择,并且会提高内存效率,因为文件操作会阻止整个事件循环的执行。
因为您收到的数据是 b64encoded
。您可以将其作为一个字节读取,并从中读取 return 一个 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")
您可以将清理任务作为参数传递给FileResponse
:
from starlette.background import BackgroundTask
# ...
def cleanup():
os.remove(temp_file)
return FileResponse(
temp_file,
background=BackgroundTask(cleanup),
)
建议发送 FileResponse
并附上删除文件或文件夹的后台任务。
click here了解更多信息
后台任务将在响应送达后 运行,因此它可以安全地删除 file/folder。
# ... 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
)
我正在使用 FastAPI 接收图像,对其进行处理,然后return将图像作为 FileResponse。
但是 returned 文件是一个临时文件,需要在端点 return 之后删除。
@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)
如何删除 return 之后的文件?
您可以删除 background task 中的文件,因为它会在 运行 发送响应后 。
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)
另一种方法是使用dependency with 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() returns 一个包含文件描述符和路径的元组。
返回 StreamingResponse
在您的情况下会是更好的选择,并且会提高内存效率,因为文件操作会阻止整个事件循环的执行。
因为您收到的数据是 b64encoded
。您可以将其作为一个字节读取,并从中读取 return 一个 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")
您可以将清理任务作为参数传递给FileResponse
:
from starlette.background import BackgroundTask
# ...
def cleanup():
os.remove(temp_file)
return FileResponse(
temp_file,
background=BackgroundTask(cleanup),
)
建议发送 FileResponse
并附上删除文件或文件夹的后台任务。
click here了解更多信息
后台任务将在响应送达后 运行,因此它可以安全地删除 file/folder。
# ... 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
)