【Python3】FastAPIでファイルのアップロードを行う方法

2022年4月15日

おはこんばんにちは、せなです。
今回はファイルのアップロードを行う方法を解説したいと思います。

フォルダ構成

今回の説明で使うフォルダ構成を簡単に載せておきますね。

  • main.py
  • files

ソースコードについて

とりあえずソースコードです。
解説については下をご確認ください。

import uvicorn
from fastapi import FastAPI, File, UploadFile

import shutil
import os

app = FastAPI()


@app.post("/files/")
async def file(file: bytes = File(...)):
    content = file.decode('utf-8')
    formatfile = content.split('\n')
    return {'filedetail': formatfile}

@app.post("/uploadfile/")
async def upload_file(file: UploadFile = File(...)):
    return {'filename': file.filename}

@app.post("/uploadfile/")
async def upload_file(file: UploadFile = File(...)):
    if file:
        filename = file.filename
        fileobj = file.file
        upload_dir = open(os.path.join(UPLOAD_DIR, filename),'wb+')
        shutil.copyfileobj(fileobj, upload_dir)
        upload_dir.close()
        return {"アップロードファイル名": filename}
    return {"Error": "アップロードファイルが見つかりません。"}

if __name__ == "__main__":
    uvicorn.run("main:app", port=8000, reload=True)

解説

Postの処理を確認したいときには「http://127.0.0.1:8000/docs」を開くと便利です!
下の様な画面が表示されるので「Try it out」で実行します。

FastAPI Post Try it out

File

小さなファイルを受け取りたいときには「bytes」を使用して、デフォルトの受け取りに「File」を使用します。

※注意点として「bytes」はメモリにファイルを保存しますので、容量の大きいファイルの受け取りには向きません。

@app.post("/files/")
async def file(file: bytes = File(...)):
    content = file.decode('utf-8')
    formatfile = content.split('\n')
    return {'filedetail': formatfile}

このPGは受け取ったファイルの内容を整形して送り返しているだけですね。

Files テスト画像

UploadFile

UploadFileはFileと違い容量の大きいファイルのやり取りに使用できます。
例えば、mp4などの動画データなどをアップロードする際にはUploadFileを使用した方が良いですね。

@app.post("/uploadfile/")
async def upload_file(file: UploadFile = File(...)):
    return {'filename': file.filename}

ファイル名を返却するだけの単純なPGです。

アップロードファイル テスト画像

ファイルの保存

FastAPIにはファイルを保存するための機能は現時点では存在していません。
代わりにPython標準のshutil.copyfileobjを使用することでファイルの保存が行えます。

UPLOAD_DIR = "./files"

@app.post("/uploadfile/")
async def upload_file(file: UploadFile = File(...)):
    if file:
        filename = file.filename
        fileobj = file.file
        upload_dir = open(os.path.join(UPLOAD_DIR, filename),'wb+')
        shutil.copyfileobj(fileobj, upload_dir)
        upload_dir.close()
        return {"アップロードファイル名": filename}
    return {"Error": "アップロードファイルが見つかりません。"}

上のPGではファイル情報を取得して、shutilのcopyfileobj()でファイル内容のコピーを行っていますね。
具体的には以下の流れです。

# ファイル情報の取得
filename = file.filename
fileobj = file.file

# 保存先のディレクトリを設定
upload_dir = open(os.path.join(UPLOAD_DIR, filename),'wb+')

# ファイルコピーの実行
shutil.copyfileobj(fileobj, upload_dir)

# 閉じる
upload_dir.close()
アップロードファイル テスト画像

最後に

今回はFastAPIでファイルをアップロードする方法について解説してみました。
Flaskではsaveを使用すればファイルの保存までできますが、FastAPIにはその辺りの機能はないんですねー

ファイルダウンロードは↓のページで解説していますので、よければどうぞ。
FastAPIでファイルのダウンロードを行う方法

全体的に使いやすいですしFastAPIはいいですね。

ではでは〜

FastAPI,Python

Posted by sena