FastAPI的异步接口在处理完成后未删除临时音频文件

编程语言 2026-07-07

我有一个FastAPI语音端点,它会把上传的音频文件保存到磁盘,进行处理,然后在一个 finally 块中尝试删除它。但文件并没有被删除。

下面是我的代码:

@app.post("/voice")
async def voice(
    telegramId: str = Form(...),
    username: str = Form(""),
    firstName: str = Form(""),
    audio: UploadFile = File(...),
):
    user = get_or_create_user(telegramId, username, firstName)
    os.makedirs("uploads", exist_ok=True)
    path = os.path.join("uploads", f"{uuid4().hex}.oga")

    try:
        with open(path, "wb") as f:
            f.write(await audio.read())

        result = voice_to_text(path)

        if not native_text:
            return {"reply": "Could not understand audio", "buttons": []}

    finally:
        if os.path.exists(path):
            os.remove(path)

解决方案

导致你的文件无法删除的原因在于文件锁定,以及 finally 块在 FastAPI 中对早期返回的处理方式。

当你把路径传给 voice_to_text(path) 时,那库会打开文件来读取它。如果它没有明确地立即释放文件句柄,操作系统就会锁定它。当你的早期 return 触发时,Python会暂停响应,先执行 finally 块。由于请求仍在积极完成中,文件仍被锁定,os.remove() 会静默失败或被阻塞。

老实说我现在没心情把完整的代码块写出来,但解决办法很简单:使用FastAPI的 BackgroundTasks

只需要把 background_tasks: BackgroundTasks 放进你的端点参数中,快速写一个类似 def remove_file(path): os.remove(path) 的辅助函数,并在保存完文件后就用 background_tasks.add_task(remove_file, path) 触发它。

如果有帮助,请告诉我!

编辑: 哦,等等,我刚意识到你也在完全泄漏FastAPI的内部临时文件。当有人上传一个 UploadFile 时,FastAPI会把它缓存到系统的 /tmp 文件夹里(如果大小超过某个阈值)。在你的代码里,你正试图删除自定义的 uploads/ 文件,但你从未调用 await audio.close()。那条流会一直保持打开,所以服务器的磁盘最终会堆满幽灵文件。确保你的后台任务在执行 await audio.close() 的同时,也执行 os.remove(),以便同时清理两者。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章