コンテンツにスキップ

第10章 ファイルのアップロード

1 フォームの作成

画像などのファイルをアップロードするには、特別なフォームが必要になります。 まず、画像アップロード用のフォームを表示するように web.py に以下を加えます。

@app.get('/imageform')
def imageup():
    return render_template('imageform.html')

imageform.htmlでは、まずフラッシュメッセージでエラーメッセージを出すようにし、その下にフォームを設置します。

<h1>画像アップロード</h1>

{% for message in get_flashed_messages() %}
    <p>{{ message }}</p>
{% endfor %}

<form action="/image" method="post" enctype="multipart/form-data">
    <input type="file" name="upfile" accept="image/*">
    <input type="submit" value="アップロード">
</form>

formタグで enctype="multipart/form-data" を指定します。これにより、ファイルのアップロードが可能になります。

そして、ファイルを選択する部品をinputタグで type="file" を指定し作成します。

今回は画像のアップロードとしたいので、accept により選択できるファイルを画像(image/*)に限定しています。

なお、今回はフォーム内にファイルアップロードの部品しかありませんが、テキストボックスなど他の入力部品も含めることが出来ます。

2 アップロード処理

web.py でのアップロード処理は以下のようになります。

@app.post('/image')
def imageup_post():
    file = request.files['upfile']
    filename = file.filename

    if filename == '':
        flash("ファイルが選択されていません")
        return redirect('/imageform')

    savepath = f'C:\\python\\web\\static\\{filename}' 
    file.save(savepath)

    return render_template('image.html',filename=filename)

まず、request.filesでアップロードしたファイルの情報を取得します。そのfilename属性にアップロードしたファイルのファイル名が入っています。これが空欄の場合、ファイルが選択されずにボタンが押されているので、リダイレクトで元のフォームに戻ります。

後は、アップロードされたファイルを file.save(パス) で保存します。保存先をstaticフォルダの中にすることで、保存したファイルを直接表示することが出来ます。

3 画像の表示

image.html ではファイル名を表示するとともに、imgタグを使い、画像を表示します。

<h1>画像アップロード完了</h1>

<p>ファイル名:{{filename}}</p>

<img src="/static/{{filename}}">

4 データベースとの連携

画像をデータベース内にデータとして直接保存することは可能ですが、その場合、データベースのデータが非常に大きくなります。そこで、画像はファイルとして保存しておき、そのファイル名をデータベースに格納するようにすることが多いです。

保存するファイル名は他と重複しないようにランダムな名前を付けます。元の名前が必要な場合には、別の列に元の名前も保存します。

# ランダムな文字列の作成例
# 事前に、import datetime, random をしておく

# 現在日時(マイクロ秒含む)
dstr = datetime.datetime.now().strftime("%Y%m%d-%H%M%S-%f")
# 最後に乱数を加える
filename = dstr + str(random.randint(0, 10000)) + ".jpg"

あるいはデータベースのデータと連携できるように、主キーでファイル名を付けます。例えば、主キーが 1 のレコードに対応する画像は image1.jpg などです。