ちょっと調べる機会があったので備忘録。 FlaskでAPI等を実装するときに、ファイルダウンロードさせる場合にどういう風に書けばいいかを調べました。
インストール
Flaskがインストールされていなければ、pipコマンドまたはpythonパッケージ管理ソフトでインストールしてください。
$ pip install flask
実装
画面なしでAPIだけ書くとこんな感じ。
- app.py
import os from flask import Flask, send_file app = Flask(__name__) @app.route("/download", methods=["GET"]) def download_api(): filepath = "./test_file.txt" filename = os.path.basename(filepath) return send_file(filepath, as_attachment=True, attachment_filename=filename, mimetype='text/plain') if __name__ == "__main__": app.run(debug=True)
上記では6行目でルーティングしている/download
をGETでアクセスすることで起動します。
8行目から、ダウンロードさせるファイルのパスを指定して、ファイル名を設定しています。今回はos.path.basename()
を使用して、ファイルパスからファイル名を抽出しています。10行目でFlaskのsend_file()
を使ってダウンロードさせるファイルを指定します。filepath
はプログラムルートからの相対パスまたは絶対パスを指定します。mimetype
はダウンロードさせるファイルのmimetypeを指定します。as_attachement=True
はヘッダ付きでファイルを送信する場合に使用します。attachment_filename
は添付ファイルのファイル名を指定します。ファイル名がダウンロードさせるファイル名と異なる場合のみ使用するため、ダウンロードさせるファイル名が同名の場合は省略することができます。
その他にもタイムアウト時間など設定できるパラメータがありますので、詳しくはFlaskの公式ドキュメントをご確認ください。
一応今回ダウンロードさせるテスト用ファイルtest_file.txt
を作っておきます。
$ echo download test > test_file.txt
試してみる
上記を実行するとAPIが立ち上がります。
$ python app.py * Serving Flask app "app" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 184-697-540
別TerminalでGETしてみましょう。
$ curl http://127.0.0.1:5000/download -o download_file.txt
取得できたファイルを確認すると、ちゃんと指定したファイルをダウンロードできていることがわかります。
$ cat download_file.txt
download test
hashで確認しても一緒になりますね。
$ sha1sum * ---- 598871b7a00d939cf22191cdc9e6faef4c3274d9 download_file.txt 598871b7a00d939cf22191cdc9e6faef4c3274d9 test_file.txt