事前準備
今回はFastAPIでファイルのアップロード機能を作成する方法について紹介していきます。
FastAPIでファイルを扱うにはリクエストボディがmultipart/formdataになります。このmultipart/formdataをFastAPIで扱えるようにするには あらかじめpython-multipartのインストールが必要です。
pip install python-multipart
ファイルのアップロード機能を作る
FastAPIでファイルのアップロード機能を作る方法として、以下の2通りの実装方法があります。
Annotated[bytes, File()]
でアノテーションするUploadFile
でアノテーションする
それぞれ紹介していきます。
Annoted[bytes, File()]
Annoted[bytes, File()]
を用いたファイルのアップロード方法では下記コードのようにAnnoted[bytes, File()]
でアノテーションを行います。
from fastapi import FastAPI, File
from typing import Annotated
app = FastAPI()
@app.post('/')
def file_upload(file: Annotated[bytes, File()]):
return file.decode()
Swagger UIで確認してみると、ファイルをアップロードできるようになっています。
また、リクエストボディもapplication/jsonではなく、multipart/form-dataとなっています。

実際に下記のテキストファイルを与えてみます。
THIS IS TEST TEXT...
レスポンスにテキストファイルの内容が返ってきており、ちゃんとファイルをアップロードできていることがわかりました。

UploadFile
Annoted[bytes, File()]
で受け取ることができていたのは、ファイルのデータでした。
一方で、UploadFile
では受け取れるものがやや異なります。
<引数>.file
で、一時的なファイルオブジェクトにアクセスできるため、データはPythonのファイルオブジェクトとして読み取ることができます。
また、データにアクセスするだけでなく、filename
でファイルの名前、content_type
でContent-typeを取得することもできます。
from fastapi import FastAPI, UploadFile
app = FastAPI()
@app.post('/')
def file_upload(file: UploadFile):
print(file.filename)
# test_upload.txt
content_byte = file.file.read()
print(file.content_type)
# text/plain
print(type(content_byte))
return content_byte.decode()

実際に下記のテキストファイルを与えてみます。
THIS IS TEST TEXT...
正しく、データを読み取ることができてそうですね。

使い分け
2つのファイルのアップロード方法について紹介しましたが、これらはどのようにして使い分けるのでしょうか?
Annoted[bytes, File()]
では、受け取ったデータはメモリーに保存されます。小さなサイズのファイルであれば良いですが、大きなファイルを受け取る場合、メモリーに保存するのは良くないかもしれません。
一方で、UploadFile
を使用した方法では、一時ファイルとしてアクセスができるように、補助記憶に保存されています(ドキュメントによると一定程度まではメモリーに保存されるらしい)。そのため、動画などの大きなファイルをアップロードする際にはメモリーを圧迫しないようにUploadFile
を使用した方が良いと言えます。
参考資料

コメント