🐥

【Python】postされたファイルを処理するために一時ファイルとして保存する【FastAPI】

2022/06/12に公開

結論

import shutil
import tempfile
from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/get_file")
def process_file(
    upload_file: UploadFile = File(...),
):
     # suffixは保存するファイルの拡張子を指定(今回は".stl"を指定)
    with tempfile.NamedTemporaryFile(delete=True, dir=".", suffix=".stl") as temp_file:
        shutil.copyfileobj(upload_file.file, temp_file)
	
	# with内であればtemp_file.nameでファイル名指定が可能
	print(temp_file.name)
	
	# ↓内部処理↓

やりたいこと

  • APIのPOSTリクエストで特定のファイルをサーバ側に送り、サーバ側で処理したい。しかし、処理後はサーバ側にファイルを残さずに処理結果だけをAPIのResponseで返したい。

具体例

  • APIリクエストで3DモデルのSTLファイルを送信し、サーバ側でOpen3Dを使ってPointCloud形式への変換や、軽量化などの処理をする場合

tempfileモジュールについて

Pythonで一時ファイルやディレクトリを作成する際は tempfile モジュールを使用する。
https://docs.python.org/ja/3/library/tempfile.html

ファイル名を今後の処理で必要としない場合は tempfile.TemporaryFile を使用する。今回は内部処理でファイル名を指定して読み込む必要があったため、作成された一時ファイルの名前の取得が可能な tempfile.NamedTemporaryFile を使用する。

FastAPIにおけるファイルの受け取り

https://fastapi.tiangolo.com/ja/tutorial/request-files/

APIからファイルを受け取る際に使用するクラスは FileUploadFile の2種類ありますが、今回は取り回しが良い UploadFile を使用する。
受け取ったUploadFileを一時ファイルなどに保存する際は shutil.copyfileobj を使用する。

shutil.copyfileobj("コピー元のファイル名", "コピー先のファイル名")

ここでコピー先のファイル名を使用するため、名前指定ができる tempfile.NamedTemporaryFile を使用する必要があった。

完成したソースコードの全体

記事先頭と同じソースコード
import shutil
import tempfile
from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/get_file")
def process_file(
    upload_file: UploadFile = File(...),
):
     # suffixは保存するファイルの拡張子を指定(今回は".stl"を指定)
    with tempfile.NamedTemporaryFile(delete=True, dir=".", suffix=".stl") as temp_file:
        shutil.copyfileobj(upload_file.file, temp_file)
	
	# with内であればtemp_file.nameでファイル名指定が可能
	print(temp_file.name)
	
	# ↓内部処理↓

参考文献

https://hibiki-press.tech/python/tempfile-md/2829
https://self-methods.com/fastapi-file/

Discussion