问题描述
我正在使用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)
解决方法
您可以删除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,'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()返回带有文件描述符和路径的元组。
,您可以将清理任务作为 FileResponse
的参数传递:
from starlette.background import BackgroundTask
# ...
def cleanup():
os.remove(temp_file)
return FileResponse(
temp_file,background=BackgroundTask(cleanup),)
,
在您的情况下,返回StreamingResponse
是一个更好的选择,并且由于文件操作将阻止事件循环的整个执行,因此可以提高内存效率。
由于您接收的数据为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")