flaskでSNSのようなwebアプリ開発をしているのですが、画像保存機能を実装できたのでまとめます。
背景
SNSのようなアプリでは画像も一緒に見えた方が文章だけの投稿よりイメージがつきやすいと思ったため、この機能を実装することにしました。
機能概要
大まかに以下のように機能を実装すればよいはずです。
- html
1-1. ファイルを受け取る
1-2. バックエンドにファイルを渡す - python(バックエンド)
2-1. ファイルを受け取る
2-2. ストレージに保存する
機能詳細
それぞれの機能を実装していきます。
1.html
ファイルの受け取りのためには、formメソッドのenctypeを"multipart/form-data"に設定する必要があります。
index.html
<h1>新規投稿</h1>
<form method="POST" enctype="multipart/form-data">
<label for="title">タイトル</label>
<input type="text" name="title">
<label for="body">内容</label>
<input type="text" name="body">
<!-- 1-1.ファイルを受け取る -->
<label for="file">写真</label>
<input type="file" name="file">
<!-- 1-2.ファイルをバックエンドに渡す -->
<input type="submit" value="投稿">
</form>
2.python
htmlでenctypeを"multipart/form-data"に設定した場合、ファイルを取得するにはrequest.files['file']とする必要があります。
request.form.get['file']としていたため、バックエンド側でうまくファイルの受け取りができませんでした。
app.py
import os
from werkzeug.utils import secure_filename
# ファイルの拡張子を指定
ALLOWED_EXTENSIONS = ['png', 'jpg', 'jpeg', 'gif']
# 画像ファイルの拡張子が指定のものかどうか確認する関数
def allowed_file(filename):
if '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS:
return True
else:
print('allowed_file: 許可されていないファイル拡張子です')
return False
# 画像をアップロードするフォルダを指定
UPLOAD_FOLDER = 'uploads'
# リクエストにファイルが含まれる場合にストレージにファイルを
def upload_file(request):
# 2-1.ファイルを受け取る
file = request.files['file']
if file is None:
return None
elif file.filename == '':
return None
elif file and allowed_file(file.filename):
filename = secure_filename(file.filename)
filepath = os.path.join(UPLOAD_FOLDER, filename)
# 2-2. ストレージに保存する
file.save(filepath)
return filepath
else:
return None
まとめ
html、pythonの箇所に記載した内容を理解できておらずファイルの受け取りがうまくできませんでした。同じ内容で進めないでいる人の助けになれば幸いです。