TSUBOCK★LABO-ツボックラボ-

とあるセキュリティエンジニアの技術メモブログ

MENU

Flaskでファイルダウンロードを実装する

ちょっと調べる機会があったので備忘録。 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

参考サイト

Flask APIリファレンス(公式)

Flaskでファイルダウンロードを実現する3つの方法