<aside>
💡 tempfile.SpooledTemporaryFile
을 래핑한 Starlette
객체로, 클라이언트 요청에 담긴 파일을 전달 받을 수 있다.
</aside>
Temporary file wrapper, specialized to switch from BytesIO or StringIO to a real file when it exceeds a certain size or when a fileno is needed.
rollover()
tempfile.Tempfile
을 사용해 디스크에 임시파일 생성
내부적으로 NamedTemporaryFile
을 사용하는데, 해당 객체는 delete
인자 (python 3.12부터는 delete_on_close
인자도 함께 사용)를 사용해 파일이 종료되는 시점을 조절할 수 있다
<aside> 💡
프로젝트에서 python 3.9를 사용하여 delete
인자만 사용 가능
</aside>
delete = true
(기본값) → 파일이 닫히게 되면 삭제되어 다시 열 수 없다delete = false
→ 파일이 닫혀도 삭제되지 않아 다시 열 수 있다 → os.unlink()
로 직접 삭제해주어야 함파일이 닫히기 전 아직 열려있는 경우
<aside> 💡
윈도우는 파일 시스템의 파일 잠금 방식이 POSIX와 달라 파일이 열려있는 경우 해당 파일에 잠금을 걸어 다른 프로세스나 핸들이 동일한 파일에 접근하는 것을 막는다
</aside>
사용 예시
from fastapi import UploadFile
# 단일 파일
@app.post("/uploadfile/")
async def upload_single_file(file: UploadFile): <---------------------
return {"filename": file.filename}
# 다중 파일
@app.post("/uploadfile/")
async def upload_multiple_file(file_list: list[UploadFile]): <---------------------
return ...
<aside> 💡 파일의 총 크기가 커질 수록 foreground에서 S3 저장까지 수행하게 되면 소요시간이 너무 길어 백그라운드에서 진행
</aside>
APIRouter
에서는 이미 메모리에서 디스크로 rollover
처리가 되어있다close()
처리가 되어 삭제된 이후였기 때문이다delete=False
인자를 사용한 NamedTemporaryFile
를 통해 직접 임시파일들을 생성하고, 그 경로들을 background에 넘겨서 여러 스레드에서 동시에 S3 업로드 및 임시파일 삭제
TemporaryFile
은 파일을 닫으면 자동 삭제되며(커스텀 불가), 백그라운드에서 해당 파일을 특정할 수 없어 NamedTemporaryFile
사용BackgroundTasks
사용 시 db 쓰기 작업 미작동ThreadPoolExecutor
스레드 수를 조절하여 재사용 [vs asyncio
의 loop.run_in_executor()
](https://fortune-lark-b0d.notion.site/vs-asyncio-loop-run_in_executor-11b1bf6ebbe581dfb343e7ff9c77439a)