#python #python-asyncio #fastapi #starlette
#python #python-asyncio #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)
Как я могу удалить файл после его возврата?
Ответ №1:
Вы можете удалить файл в фоновой задаче, так как он будет запущен после отправки ответа.
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('TESTn')
background_tasks.add_task(remove_file, path)
return FileResponse(path)
Другой подход заключается в использовании зависимости с выходом. Код 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('TESTn')
try:
yield path
finally:
os.unlink(path)
@app.post("/send")
async def send(file_path=Depends(create_temp_file)):
return FileResponse(file_path)
Примечание: mkstemp() возвращает кортеж с дескриптором файла и путем.
Ответ №2:
Вы можете передать задачу очистки в качестве параметра FileResponse
:
from starlette.background import BackgroundTask
# ...
def cleanup():
os.remove(temp_file)
return FileResponse(
temp_file,
background=BackgroundTask(cleanup),
)
ОБНОВЛЕНИЕ 12-08-2022
Если кто-то генерирует имя файла динамически, то можно передать параметры фоновой задаче, например, следующим образом
return FileResponse(
temp_file,
background=BackgroundTask(cleanup, file_path),
)
Затем cleanup
функцию необходимо адаптировать для принятия параметра, который будет именем файла, и вызвать os.remove
функцию с именем файла в качестве параметра вместо глобальной переменной
Ответ №3:
Рекомендуется отправлять 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
)