フラスコ send_file()

Salman Mehmood 2023年6月21日
フラスコ send_file()

この説明では、ファイルを SQLAlchemy データベースにアップロードし、それらのファイルを Flask のデータベースからダウンロードする方法を学びます。

Flask で SQLAlchemy データベースからファイルをアップロードおよびダウンロードする

SQLAlchemy を使用した基本的な Flask アプリがあり、テンプレートを使用してデータベースからファイルをアップロードおよびダウンロードします。 send_file() 関数を使用すると、HTML の代わりにファイルを返すことができます。

from flask import Flask, request, send_file, render_template
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db.sqlite3"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)


@app.route("/", methods=["GET", "POST"])
def Main_page():
    return render_template("index.html")

index.html ファイル内に単純なフォームを作成しました。 ファイルをアップロードするフォームで作業する場合は、enctype="multipart/form-data" を使用する必要があります。これがないと機能しません。

ここで、最初に行う必要があるのは、ファイルに関する情報とファイルのデータを保持するモデルを作成することです。 このクラスを File_Uploader と呼びます。これは SQLAlchemy モデルになります。

このモデルにはいくつかのフィールドが必要になるため、主キーとなる ID を作成し、次に、ユーザーがフォームからファイルをアップロードするときのファイル名となる File_Name を追加します。 最後は DATA で、データベース内に保存されているファイルの生データです。

この特定のデータには、LargeBinary と呼ばれるデータ型を使用する必要があります。これにより、任意のバイナリ データをデータベースに格納できます。 通常、ファイルはデータベースに保存されませんが、メタデータはデータベースに保存されることに注意してください。

多くのファイルがない場合、または制限のためにすべてをデータベースに保持したい場合は、データベースにファイルを格納できます。 ファイル データを 1つのテーブル内の他の列と組み合わせると、パフォーマンスの問題が発生する可能性があります。

ファイルデータを含むこのテーブルが大きくなると、パフォーマンスの問題が発生する可能性がありますが、必要に応じて実行できます。 それが私たちがこれを作成している理由です。

class File_Uploader(db.Model):
    File_ID = db.Column(db.Integer, primary_key=True)
    File_Name = db.Column(db.String(50))
    DATA = db.Column(db.LargeBinary)

フォームからファイルを取得し、それが機能することを確認します。 Main_page() 関数内で、投稿リクエストを処理する if ステートメントを設定します。

ここで、request.files['file'] を使用してファイルを取得し、それらを変数に格納して、Got_File という名前を付けます。 これにより、フォームから送信された特定のキーを使用して、リクエストで送信されたすべてのファイルが取得されます。

if request.method == "POST":
    Got_File = request.files["file"]

次のステップでは、これをデータベースにアップロードします。これは、File_Uploader というモデルを使用します。 Got_File.filenameFile_Name フィールドに渡し、次にファイルのデータを DATA フィールドに渡します。

Got_File.read() は、ファイルのすべてのバイナリ データを取得し、それをどこにでも割り当てます。 次に、セッションを追加してデータをコミットします。

file_upload = File_Uploader(File_Name=Got_File.filename, DATA=Got_File.read())
db.session.add(file_upload)
db.session.commit()
return f"Uploaded: {Got_File.filename}"

次に、データベースとデータベース内にテーブルを作成する必要があるため、app.py ファイルが配置されているディレクトリと同じディレクトリで Python シェルを開き、次のコマンドを使用します。

from app import db

db.create_all()

ルート ディレクトリを見ると、db というデータベース ファイルがあります。 このファイルを SQLite ビューアー内にドラッグすると、テーブルが作成されていることがわかります。

Flask send_file() 出力 1

次に、このアプリを実行してファイルをアップロードします。 次に、フォームからファイルをアップロードできるようになります。

サーバーを実行した後、フォームにアクセスしてファイルを送信するルートにアクセスします。 これらのコマンドを使用して、Flask アプリをセットアップし、このアプリを実行します。

set FLASK_APP='app.py'
flask run

ファイルをアップロードした後、ファイルが正常にアップロードされたことを確認できます。テーブルを見ると、ID とファイル名が表示されます。

Flask send_file() 出力 2

あらゆる種類のファイルをアップロードできます。 mp3、ムービー ファイル、コード ファイルなど、どのようなものでもかまいません。

ここで、データベースにアップロードしたファイルをダウンロードするルートを作成します。このルートには、File_ID という変数があります。 次に、その ID を使用してデータベースでクエリを実行し、その特定の行のデータをデータベースから取得します。

@app.route('/download/<File_ID>')

io モジュールから BytesIO クラスをインポートする必要があります。 これにより、データベース内のバイナリ データを取得し、Flask がファイルの再生成に使用できる形式に変換できます。

send_file() 関数を使用してファイルを返します。 次に、BytesIO クラス内で、対応する列でデータを渡します。

次に、添付ファイルを使用するため、attachment_filename キーワード引数を渡します。

def download(File_ID):
    Got_File = File_Uploader.query.filter_by(File_ID=File_ID).first()
    return send_file(
        BytesIO(Got_File.DATA),
        attachment_filename=Got_File.File_Name,
        as_attachment=True,
    )

これを見てみましょう。 ダウンロード ページに移動し、ID を渡します。 このルートに到達すると、ファイルをダウンロードできます。

Flask send_file() 出力 3

完全な Python コード:

from flask import Flask, request, send_file, render_template
from flask_sqlalchemy import SQLAlchemy
from io import BytesIO

app = Flask(__name__)

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db.sqlite3"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)


class File_Uploader(db.Model):
    File_ID = db.Column(db.Integer, primary_key=True)
    File_Name = db.Column(db.String(50))
    DATA = db.Column(db.LargeBinary)


@app.route("/", methods=["GET", "POST"])
def Main_page():
    if request.method == "POST":
        Got_File = request.files["file"]

        file_upload = File_Uploader(File_Name=Got_File.filename, DATA=Got_File.read())
        db.session.add(file_upload)
        db.session.commit()

        return f"Uploaded: {Got_File.filename}"
    return render_template("index.html")


@app.route("/download/<File_ID>")
def download(File_ID):
    Got_File = File_Uploader.query.filter_by(File_ID=File_ID).first()
    return send_file(
        BytesIO(Got_File.DATA),
        attachment_filename=Got_File.File_Name,
        as_attachment=True,
    )

Flask アプリ内で使用した HTML ファイル:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File Uploader </title>
    <style>
        body {
          margin: 0;
        }

        .center {
          display: flex;
          justify-content: center;
          align-items: center;
          height: 100vh;
        }
      </style>
</head>
<body>
    <div class="center">
        <form method="POST" action="/" enctype="multipart/form-data">
            <input type="file" name="file">
            <button>Submit</button>
        </form>
    </div>
</body>
</html>
著者: Salman Mehmood
Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

関連記事 - Flask File