クライアントからファイルを送信してサーバーに保存できるみたいです。
実用的な雰囲気出ていますね。
Flaskチュートリアル、クイックスタートの「File Uploads」を進めていきます。進めているチュートリアルページはこちらになります。
https://flask.palletsprojects.com/en/1.1.x/quickstart/#file-uploads
こんな人の役に立つかも
・flaskを勉強している人
・PythonでWebアプリケーションを作りたい人
・flaskでファイルのアップロードをしたい人
File Uploadsをプログラミング
Flaskチュートリアルのプログラムを元に、アップロードを行うプログラムを作成しました。
今回も、チュートリアルだけではよくわかりませんでした・・・
ファイルの構成
プロジェクトフォルダはこのような構成になりました。今回作成したのは、下の図の赤線のファイル、フォルダになります。
必要となるファイル、フォルダは次の通りです。
①application.py
前回のログインで利用したapplication.pyに追記していきます。
②uploads.html
ファイルをアップロードするためのフォームを記載したHTMLテンプレートです。
③finished.html
アップロードができたら表示するアップロード完了画面HTMLテンプレートです。
④uploadsフォルダ
アップロードしたファイルを保存するための階層です。
①application.py
前回の記事で試したログインのサンプルプログラムに「@app.route(‘/uploads’)」のブロックを追加しています。
from flask import Flask, url_for
from markupsafe import escape
from flask import request
from flask import render_template
app = Flask(__name__)
@app.route('/')
def index():
return 'Index'
@app.route('/login', methods=['POST', 'GET'])
def login():
if request.method == 'POST':
if request.form['username'] and request.form['password']:
return render_template('in.html',
username=request.form['username'],
password=request.form['password'])
return render_template('login.html')
#↓今回追加したプログラム
#クライアントの命名したファイル名を利用するためのsecure_filename()
from werkzeug.utils import secure_filename
@app.route('/uploads', methods=['POST', 'GET'])
def upload_file():
if request.method == 'POST':
f = request.files["the_file"]
#任意の階層をフルパスで指定(macの場合。任意のユーザー名は変更してください。)
f.save('/Users/任意のユーザー名/Python/myproject/uploads/' + secure_filename(f.filename))
#アップロードしてサーバーにファイルが保存されたらfinishedを表示
return render_template('finished.html')
else:
#GETでアクセスされた時、uploadsを表示
return render_template('uploads.html')
「localhost:5000/uploads」にアクセスすると、uploads.htmlのフォームが表示されます。「POST」メソッドでアクセス(フォームに入力して送信ボタンをおすと)すると、if条件文の中に入り、フォームで選択したファイルを任意の階層に保存します。
この時、ユーザー指定のファイル名をそのまま使うときには、セキュリティに配慮する必要があり、そのためにimportしたsecure_filenameメソッドを利用しています。
最後に、「finished.html」テンプレートを表示するようにしています。
プログラムに厚みが出てきた感じがします。
②uploads.html
一般的なHTMLによるフォームデータです。
<!doctypehtml>
<html>
<head>
<meta charset="utf8"/>
</head>
<body>
<h1>アップロードフォーム</h1>
<form method="POST" action="/uploads" enctype="multipart/form-data">
<input placeholder="お名前" name="username" type="text"/>
<input placeholder="データ" name="the_file" type="file"/>
<input value="送信" type="submit"/>
</form>
</body>
</html>
ファイルを送信する際に、「enctype=”multipart/form-data”」とする点がポイントです。そして、ファイルをアップロードする「input」にはapplication.pyで受け取っている「the_file」という名前でデータを渡します。
③finished.html
かなり雑なHTMLですが、アップロード完了、と表示するためだけのHTMLテンプレートになります。
<html>
<body>
<h1>アップロード完了</h1>
</body>
</html>
④uploadsフォルダ
application.pyで、この階層をフルパスで指定してフォームで選択したファイルをここに保存します。
フルパスじゃないやり方はよくわかっていません・・・
動作の確認と検証
Pythonの仮想環境でデバッグ用Webサーバーを立ち上げて、「localhost:5000/uploads」へとアクセスします。
Pythonの仮想環境とデバッグ用Webサーバーにつきましては、次の記事もご参考ください。
アクセスすると、アップロードフォームが出てきます。この状態が、GETでリクエストを出した状態となります。
適当なテキストファイルなどを作成して、「ファイルを選択」ボタンからアップロードしてみます。
今回、私はこの画像をアップロードしてみました。
ファイルを選択したら「送信」ボタンを押します。
しっかりと「finished.html」へ遷移していることがわかります。
ここで、myprojectの「uploads」フォルダを確認してみます。
uploadsフォルダに「panda.png」が保存されています。
チュートリアルには、アップロードに関するより詳しい説明ページがあるようです。パッとみた感じで、ファイルサイズの制限や、拡張しでの制限など、より実用的な部分が記載してあるようなので、こちらも少し目を通してみようかと思います。