Web

[Python] Bottleでファイルアップローダーを実装する方法

Bottleでファイルアップローダーを実装するには、bottleモジュールを使用してHTTPリクエストを処理します。

まず、HTMLフォームでenctype="multipart/form-data"を指定し、ファイルをアップロードできるようにします。

サーバー側では、request.filesを使ってアップロードされたファイルを取得し、save()メソッドで保存します。

request.files.get('file')でファイルオブジェクトを取得し、file.save()で指定したディレクトリに保存できます。

目次から探す
  1. Bottleとは
  2. Bottleのインストールと基本設定
  3. ファイルアップロードの仕組み
  4. Bottleでのファイルアップロードの実装
  5. ファイルアップロードのバリデーション
  6. ファイルアップロードのエラーハンドリング
  7. Bottleでのファイルダウンロードの実装
  8. 応用例:複数ファイルのアップロード
  9. 応用例:画像ファイルのアップロードと表示
  10. 応用例:アップロードされたファイルのデータベース保存
  11. まとめ

Bottleとは

Bottleは、Pythonで書かれたシンプルで軽量なWebフレームワークです。

特に小規模なアプリケーションやプロトタイプの開発に適しており、単一のファイルで構成されるため、導入が非常に簡単です。

Bottleは、RESTfulなルーティング、テンプレートエンジン、セッション管理などの基本的な機能を提供し、必要に応じて拡張することも可能です。

また、Bottleは依存関係が少なく、他のライブラリやフレームワークと組み合わせて使用することができるため、柔軟性が高いのも特徴です。

これにより、開発者は迅速にアプリケーションを構築し、デプロイすることができます。

Bottleのインストールと基本設定

Bottleのインストール方法

BottleはPythonのパッケージ管理ツールであるpipを使用して簡単にインストールできます。

以下のコマンドを実行することで、Bottleをインストールできます。

pip install bottle

このコマンドを実行すると、BottleがPython環境にインストールされます。

インストールが完了したら、Bottleを使用したアプリケーションを開発する準備が整います。

最初のBottleアプリケーションの作成

Bottleを使って最初のアプリケーションを作成するには、以下のようなコードを書きます。

from bottle import Bottle, run
app = Bottle()
@app.route('/')
def home():
    return "こんにちは、Bottleアプリケーション!"
if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このコードを実行すると、ローカルホストの8080ポートでBottleアプリケーションが起動します。

ブラウザでhttp://localhost:8080にアクセスすると、「こんにちは、Bottleアプリケーション!」というメッセージが表示されます。

Bottleの基本的なルーティング

Bottleでは、URLに対して特定の処理を行うためのルーティングを簡単に設定できます。

以下は、異なるURLパスに対して異なるレスポンスを返す例です。

from bottle import Bottle, run
app = Bottle()
@app.route('/')
def home():
    return "ホームページ"
@app.route('/about')
def about():
    return "このアプリケーションについて"
@app.route('/contact')
def contact():
    return "お問い合わせページ"
if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このコードを実行した後、ブラウザでそれぞれのURLにアクセスすると、対応するメッセージが表示されます。

例えば、http://localhost:8080/aboutにアクセスすると、「このアプリケーションについて」というメッセージが表示されます。

これにより、Bottleの基本的なルーティングの使い方が理解できます。

ファイルアップロードの仕組み

HTTPにおけるファイルアップロードの仕組み

HTTPプロトコルでは、クライアントがサーバーにデータを送信するために、特定のリクエストメソッドを使用します。

ファイルアップロードの場合、主にPOSTメソッドが使用されます。

クライアントは、ファイルを含むデータをHTTPリクエストのボディに含めてサーバーに送信します。

サーバーは受け取ったデータを解析し、指定された場所にファイルを保存します。

このプロセスは、以下のような流れで行われます。

  1. ユーザーがファイルを選択し、アップロードボタンをクリックする。
  2. ブラウザがファイルを含むHTTPリクエストをサーバーに送信する。
  3. サーバーがリクエストを受け取り、ファイルを保存する処理を行う。

multipart/form-dataとは

ファイルアップロードを行う際、HTTPリクエストのContent-Typeとしてmultipart/form-dataが指定されます。

この形式は、複数のデータを一つのリクエストで送信するためのもので、特にファイルデータを含む場合に使用されます。

multipart/form-dataでは、各データ部分が境界文字列で区切られ、各部分には名前やファイル名、MIMEタイプなどのメタデータが含まれます。

これにより、サーバーは受け取ったデータを正しく解析し、ファイルを適切に処理することができます。

ファイルアップロードに必要なHTMLフォームの構成

ファイルをアップロードするためには、HTMLフォームを作成する必要があります。

以下は、ファイルアップロード用の基本的なHTMLフォームの例です。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ファイルアップロードフォーム</title>
</head>
<body>
    <h1>ファイルアップロード</h1>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <label for="file">ファイルを選択:</label>
        <input type="file" id="file" name="file" required>
        <button type="submit">アップロード</button>
    </form>
</body>
</html>

このフォームでは、<form>タグのenctype属性にmultipart/form-dataを指定しています。

これにより、選択されたファイルが正しくサーバーに送信されるようになります。

ユーザーがファイルを選択し、アップロードボタンをクリックすると、指定されたaction属性のURL(この場合は/upload)にファイルが送信されます。

Bottleでのファイルアップロードの実装

ファイルアップロード用のHTMLフォームの作成

ファイルアップロードを実装するためには、まずHTMLフォームを作成します。

以下は、Bottleアプリケーションで使用するファイルアップロード用のHTMLフォームの例です。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ファイルアップロードフォーム</title>
</head>
<body>
    <h1>ファイルアップロード</h1>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <label for="file">ファイルを選択:</label>
        <input type="file" id="file" name="file" required>
        <button type="submit">アップロード</button>
    </form>
</body>
</html>

このフォームは、ユーザーがファイルを選択し、アップロードするためのインターフェースを提供します。

enctype属性にmultipart/form-dataを指定することで、ファイルデータが正しく送信されるようになります。

Bottleでのファイル受け取り処理

次に、Bottleアプリケーションでファイルを受け取るための処理を実装します。

以下のコードは、ファイルを受け取るためのルーティングを設定した例です。

from bottle import Bottle, run, request, template
app = Bottle()
@app.route('/')
def upload_form():
    return template('upload_form')  # HTMLフォームを表示
@app.route('/upload', method='POST')
def upload_file():
    upload = request.files.get('file')  # アップロードされたファイルを取得
    return f"ファイル '{upload.filename}' がアップロードされました。"
if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このコードでは、/uploadエンドポイントにPOSTリクエストが送信されたときに、アップロードされたファイルを取得し、そのファイル名を表示します。

request.filesの使い方

Bottleでは、request.filesを使用してアップロードされたファイルにアクセスできます。

request.filesは、アップロードされたファイルの情報を含む辞書のようなオブジェクトです。

以下は、request.filesを使ってファイルを取得する例です。

@app.route('/upload', method='POST')
def upload_file():
    upload = request.files.get('file')  # 'file'はHTMLフォームのinput要素のname属性
    if upload:
        return f"ファイル '{upload.filename}' がアップロードされました。"
    return "ファイルがアップロードされませんでした。"

このコードでは、request.files.get('file')を使用して、HTMLフォームで指定したname属性に基づいてファイルを取得しています。

アップロードされたファイルの保存方法

アップロードされたファイルをサーバーに保存するには、saveメソッドを使用します。

以下は、ファイルを指定したディレクトリに保存する例です。

@app.route('/upload', method='POST')
def upload_file():
    upload = request.files.get('file')
    if upload:
        save_path = f"./uploads/{upload.filename}"  # 保存先のパスを指定
        upload.save(save_path)  # ファイルを保存
        return f"ファイル '{upload.filename}' が '{save_path}' に保存されました。"
    return "ファイルがアップロードされませんでした。"

このコードでは、upload.save(save_path)を使用して、指定したパスにファイルを保存しています。

ファイルの保存先ディレクトリの指定

ファイルを保存する際には、保存先のディレクトリを事前に作成しておく必要があります。

以下は、保存先ディレクトリを作成する方法の例です。

import os
# 保存先ディレクトリを指定
upload_dir = './uploads'
if not os.path.exists(upload_dir):
    os.makedirs(upload_dir)  # ディレクトリが存在しない場合は作成
@app.route('/upload', method='POST')
def upload_file():
    upload = request.files.get('file')
    if upload:
        save_path = os.path.join(upload_dir, upload.filename)  # 保存先のパスを指定
        upload.save(save_path)  # ファイルを保存
        return f"ファイル '{upload.filename}' が '{save_path}' に保存されました。"
    return "ファイルがアップロードされませんでした。"

このコードでは、os.makedirsを使用して、指定したディレクトリが存在しない場合に作成しています。

これにより、ファイルを安全に保存することができます。

ファイルアップロードのバリデーション

ファイルアップロードを行う際には、セキュリティやユーザー体験を向上させるために、いくつかのバリデーションを実施することが重要です。

以下では、ファイルサイズの制限、ファイル形式のチェック、ファイル名の安全性確保について説明します。

ファイルサイズの制限

アップロードされるファイルのサイズを制限することで、サーバーのリソースを保護し、悪意のある攻撃を防ぐことができます。

以下は、ファイルサイズを制限する方法の例です。

MAX_FILE_SIZE = 5 * 1024 * 1024  # 最大ファイルサイズを5MBに設定
@app.route('/upload', method='POST')
def upload_file():
    upload = request.files.get('file')
    if upload:
        if upload.size > MAX_FILE_SIZE:
            return "エラー: ファイルサイズが大きすぎます。最大サイズは5MBです。"
        save_path = f"./uploads/{upload.filename}"
        upload.save(save_path)
        return f"ファイル '{upload.filename}' が '{save_path}' に保存されました。"
    return "ファイルがアップロードされませんでした。"

このコードでは、upload.sizeを使用してファイルのサイズを取得し、最大サイズを超えている場合はエラーメッセージを返します。

ファイル形式のチェック

特定のファイル形式のみを受け入れることで、セキュリティリスクを軽減できます。

以下は、許可されたファイル形式をチェックする方法の例です。

ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}  # 許可するファイル形式
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', method='POST')
def upload_file():
    upload = request.files.get('file')
    if upload:
        if not allowed_file(upload.filename):
            return "エラー: 許可されていないファイル形式です。"
        save_path = f"./uploads/{upload.filename}"
        upload.save(save_path)
        return f"ファイル '{upload.filename}' が '{save_path}' に保存されました。"
    return "ファイルがアップロードされませんでした。"

このコードでは、allowed_file関数を使用して、ファイル名の拡張子が許可された形式に含まれているかを確認しています。

ファイル名の安全性確保

アップロードされたファイル名が安全であることを確認することも重要です。

悪意のあるユーザーがファイル名を操作して、サーバーに不正なファイルを保存することを防ぐために、ファイル名をサニタイズすることが推奨されます。

以下は、ファイル名を安全に処理する方法の例です。

import secure_filename  # 例: Flaskのsecure_filenameを使用する場合
@app.route('/upload', method='POST')
def upload_file():
    upload = request.files.get('file')
    if upload:
        if not allowed_file(upload.filename):
            return "エラー: 許可されていないファイル形式です。"
        
        safe_filename = secure_filename(upload.filename)  # ファイル名を安全に処理
        save_path = f"./uploads/{safe_filename}"
        upload.save(save_path)
        return f"ファイル '{safe_filename}' が '{save_path}' に保存されました。"
    return "ファイルがアップロードされませんでした。"

このコードでは、secure_filename関数を使用して、ファイル名を安全な形式に変換しています。

これにより、ファイル名に含まれる危険な文字やパス情報を排除し、セキュリティを向上させることができます。

ファイルアップロードのエラーハンドリング

ファイルアップロードの際には、さまざまなエラーが発生する可能性があります。

これらのエラーに適切に対処することで、ユーザーにとって使いやすいアプリケーションを提供できます。

以下では、ファイルがアップロードされなかった場合の処理、不正なファイル形式がアップロードされた場合の処理、ファイルサイズが大きすぎる場合の処理について説明します。

ファイルがアップロードされなかった場合の処理

ユーザーがファイルを選択せずにアップロードボタンをクリックした場合、ファイルがアップロードされないことがあります。

この場合には、エラーメッセージを表示して、ユーザーに再度ファイルを選択するよう促すことが重要です。

以下は、その処理の例です。

@app.route('/upload', method='POST')
def upload_file():
    upload = request.files.get('file')
    if not upload:
        return "エラー: ファイルが選択されていません。再度ファイルを選択してください。"
    
    # ここに他のバリデーション処理を追加
    save_path = f"./uploads/{upload.filename}"
    upload.save(save_path)
    return f"ファイル '{upload.filename}' が '{save_path}' に保存されました。"

このコードでは、uploadNoneの場合にエラーメッセージを返しています。

不正なファイル形式がアップロードされた場合の処理

ユーザーが許可されていないファイル形式をアップロードした場合には、エラーメッセージを表示して、再度正しい形式のファイルを選択するように促します。

以下は、その処理の例です。

@app.route('/upload', method='POST')
def upload_file():
    upload = request.files.get('file')
    if not upload:
        return "エラー: ファイルが選択されていません。再度ファイルを選択してください。"
    
    if not allowed_file(upload.filename):
        return "エラー: 許可されていないファイル形式です。PNG、JPG、JPEG、GIF形式のファイルを選択してください。"
    
    save_path = f"./uploads/{upload.filename}"
    upload.save(save_path)
    return f"ファイル '{upload.filename}' が '{save_path}' に保存されました。"

このコードでは、allowed_file関数を使用してファイル形式をチェックし、不正な形式の場合にはエラーメッセージを返しています。

ファイルサイズが大きすぎる場合の処理

ファイルサイズが設定した制限を超えている場合には、エラーメッセージを表示して、ユーザーにファイルサイズを確認するように促します。

以下は、その処理の例です。

MAX_FILE_SIZE = 5 * 1024 * 1024  # 最大ファイルサイズを5MBに設定
@app.route('/upload', method='POST')
def upload_file():
    upload = request.files.get('file')
    if not upload:
        return "エラー: ファイルが選択されていません。再度ファイルを選択してください。"
    
    if not allowed_file(upload.filename):
        return "エラー: 許可されていないファイル形式です。PNG、JPG、JPEG、GIF形式のファイルを選択してください。"
    
    if upload.size > MAX_FILE_SIZE:
        return "エラー: ファイルサイズが大きすぎます。最大サイズは5MBです。"
    
    save_path = f"./uploads/{upload.filename}"
    upload.save(save_path)
    return f"ファイル '{upload.filename}' が '{save_path}' に保存されました。"

このコードでは、upload.sizeを使用してファイルサイズをチェックし、制限を超えている場合にはエラーメッセージを返しています。

これにより、ユーザーはファイルサイズを確認し、適切なファイルを選択することができます。

Bottleでのファイルダウンロードの実装

ファイルダウンロード機能を実装することで、ユーザーがサーバーに保存されたファイルを簡単に取得できるようになります。

以下では、Bottleを使用したファイルダウンロードの実装方法について説明します。

ファイルダウンロード用のルーティング

まず、ファイルダウンロード用のルーティングを設定します。

以下のコードは、特定のファイルをダウンロードするためのエンドポイントを作成する例です。

from bottle import Bottle, run, response
app = Bottle()
@app.route('/download/<filename>')
def download_file(filename):
    # ここでファイルの存在を確認し、ダウンロード処理を行う
    return f"ファイル '{filename}' をダウンロードします。"
if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このコードでは、/download/<filename>というエンドポイントを設定しています。

<filename>はダウンロードするファイルの名前を指定するためのプレースホルダーです。

ファイルをレスポンスとして返す方法

ファイルをレスポンスとして返すには、responseオブジェクトを使用します。

以下は、指定されたファイルをダウンロードするための処理を実装した例です。

import os
@app.route('/download/<filename>')
def download_file(filename):
    file_path = os.path.join('./uploads', filename)  # 保存先のパスを指定
    if os.path.exists(file_path):
        return response.stream(open(file_path, 'rb'), headers={
            'Content-Disposition': f'attachment; filename="{filename}"'
        })
    return "エラー: ファイルが見つかりません。"

このコードでは、指定されたファイルが存在するかを確認し、存在する場合はresponse.streamを使用してファイルをストリームとして返します。

Content-Dispositionヘッダーを設定することで、ブラウザがファイルをダウンロードするように指示しています。

ファイルのMIMEタイプの設定

ファイルのMIMEタイプを設定することで、ブラウザがファイルの種類を正しく認識できるようになります。

以下は、MIMEタイプを設定する方法の例です。

import mimetypes
@app.route('/download/<filename>')
def download_file(filename):
    file_path = os.path.join('./uploads', filename)  # 保存先のパスを指定
    if os.path.exists(file_path):
        mime_type, _ = mimetypes.guess_type(file_path)  # MIMEタイプを推測
        response.content_type = mime_type or 'application/octet-stream'  # MIMEタイプを設定
        return response.stream(open(file_path, 'rb'), headers={
            'Content-Disposition': f'attachment; filename="{filename}"'
        })
    return "エラー: ファイルが見つかりません。"

このコードでは、mimetypes.guess_typeを使用してファイルのMIMEタイプを推測し、response.content_typeに設定しています。

これにより、ブラウザがファイルを適切に処理できるようになります。

ファイルが見つからない場合には、エラーメッセージを返します。

応用例:複数ファイルのアップロード

複数のファイルを一度にアップロードできる機能は、ユーザーにとって便利です。

以下では、Bottleを使用して複数ファイルのアップロードを実装する方法について説明します。

複数ファイルをアップロードするHTMLフォームの作成

まず、複数のファイルを選択できるHTMLフォームを作成します。

以下は、その例です。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>複数ファイルアップロードフォーム</title>
</head>
<body>
    <h1>複数ファイルアップロード</h1>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <label for="files">ファイルを選択:</label>
        <input type="file" id="files" name="files" multiple required>
        <button type="submit">アップロード</button>
    </form>
</body>
</html>

このフォームでは、<input>タグのmultiple属性を指定することで、ユーザーが複数のファイルを選択できるようにしています。

複数ファイルを処理するBottleのコード

次に、Bottleアプリケーションで複数ファイルを受け取るための処理を実装します。

以下は、その例です。

from bottle import Bottle, run, request, template
app = Bottle()
@app.route('/')
def upload_form():
    return template('upload_form')  # HTMLフォームを表示
@app.route('/upload', method='POST')
def upload_files():
    uploads = request.files.getall('files')  # 複数ファイルを取得
    saved_files = []
    
    for upload in uploads:
        save_path = f"./uploads/{upload.filename}"
        upload.save(save_path)  # 各ファイルを保存
        saved_files.append(upload.filename)
    
    return f"ファイル {', '.join(saved_files)} がアップロードされました。"
if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このコードでは、request.files.getall('files')を使用して、アップロードされたすべてのファイルを取得しています。

各ファイルをループで処理し、指定したパスに保存しています。

複数ファイルのバリデーション

複数ファイルをアップロードする際にも、各ファイルに対してバリデーションを行うことが重要です。

以下は、ファイルサイズと形式のバリデーションを追加した例です。

MAX_FILE_SIZE = 5 * 1024 * 1024  # 最大ファイルサイズを5MBに設定
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}  # 許可するファイル形式
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', method='POST')
def upload_files():
    uploads = request.files.getall('files')  # 複数ファイルを取得
    saved_files = []
    errors = []
    for upload in uploads:
        if upload.size > MAX_FILE_SIZE:
            errors.append(f"エラー: '{upload.filename}' はサイズが大きすぎます。")
            continue
        
        if not allowed_file(upload.filename):
            errors.append(f"エラー: '{upload.filename}' は許可されていないファイル形式です。")
            continue
        
        save_path = f"./uploads/{upload.filename}"
        upload.save(save_path)  # 各ファイルを保存
        saved_files.append(upload.filename)
    response_message = ""
    if saved_files:
        response_message += f"ファイル {', '.join(saved_files)} がアップロードされました。"
    if errors:
        response_message += " " + " ".join(errors)
    return response_message
if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このコードでは、各ファイルに対してサイズと形式のバリデーションを行い、エラーがあった場合にはエラーメッセージをリストに追加しています。

アップロードが成功したファイルとエラーがあったファイルの情報をまとめて返すことで、ユーザーにわかりやすいフィードバックを提供しています。

応用例:画像ファイルのアップロードと表示

画像ファイルのアップロードと表示機能を実装することで、ユーザーが画像を簡単にアップロードし、ウェブページ上で表示できるようになります。

以下では、Bottleを使用して画像ファイルのアップロードと表示を実装する方法について説明します。

画像ファイルのアップロード処理

まず、画像ファイルをアップロードするためのHTMLフォームを作成します。

以下は、その例です。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>画像ファイルアップロードフォーム</title>
</head>
<body>
    <h1>画像ファイルアップロード</h1>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <label for="image">画像を選択:</label>
        <input type="file" id="image" name="image" accept="image/*" required>
        <button type="submit">アップロード</button>
    </form>
</body>
</html>

このフォームでは、accept属性を使用して、画像ファイルのみを選択できるようにしています。

アップロードされた画像の保存

次に、Bottleアプリケーションで画像ファイルを受け取り、保存する処理を実装します。

以下は、その例です。

from bottle import Bottle, run, request, template
import os
app = Bottle()
UPLOAD_DIR = './uploads/images'
if not os.path.exists(UPLOAD_DIR):
    os.makedirs(UPLOAD_DIR)  # 保存先ディレクトリを作成
@app.route('/')
def upload_form():
    return template('upload_form')  # HTMLフォームを表示
@app.route('/upload', method='POST')
def upload_image():
    upload = request.files.get('image')  # アップロードされた画像を取得
    if upload:
        save_path = os.path.join(UPLOAD_DIR, upload.filename)  # 保存先のパスを指定
        upload.save(save_path)  # 画像を保存
        return f"画像 '{upload.filename}' がアップロードされました。"
    return "エラー: 画像がアップロードされませんでした。"
if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このコードでは、request.files.get('image')を使用してアップロードされた画像を取得し、指定したディレクトリに保存しています。

アップロードされた画像を表示するルーティング

アップロードされた画像を表示するためのルーティングを設定します。

以下は、画像を表示するためのエンドポイントの例です。

@app.route('/images/<filename>')
def serve_image(filename):
    file_path = os.path.join(UPLOAD_DIR, filename)  # 画像のパスを指定
    if os.path.exists(file_path):
        return static_file(filename, root=UPLOAD_DIR)  # 画像をレスポンスとして返す
    return "エラー: 画像が見つかりません。"
if __name__ == '__main__':
    run(app, host='localhost', port=8080)

このコードでは、/images/<filename>というエンドポイントを設定し、指定された画像ファイルを返すようにしています。

static_file関数を使用することで、指定したディレクトリから画像を直接返すことができます。

画像の表示

アップロードされた画像を表示するためには、HTMLで画像のURLを指定します。

以下は、画像を表示するためのHTMLの例です。

<img src="/images/アップロードされた画像のファイル名" alt="アップロードされた画像">

このようにすることで、ユーザーがアップロードした画像をウェブページ上で表示することができます。

画像のファイル名は、実際にアップロードされたファイル名に置き換えてください。

これにより、ユーザーはアップロードした画像を確認できるようになります。

応用例:アップロードされたファイルのデータベース保存

ファイルをアップロードする際に、そのメタデータやファイルパスをデータベースに保存することで、後からファイルを管理しやすくなります。

以下では、Bottleを使用してアップロードされたファイルのメタデータをデータベースに保存し、ファイルを取得して表示する方法について説明します。

ファイルのメタデータをデータベースに保存する方法

まず、SQLiteを使用してデータベースを作成し、ファイルのメタデータを保存するためのテーブルを作成します。

以下は、テーブルを作成するためのコードの例です。

import sqlite3
# データベースの接続
conn = sqlite3.connect('files.db')
c = conn.cursor()
# テーブルの作成
c.execute('''
CREATE TABLE IF NOT EXISTS files (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    filename TEXT NOT NULL,
    upload_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
conn.close()

このコードでは、filesというテーブルを作成し、ファイル名とアップロード日時を保存するためのカラムを定義しています。

次に、ファイルをアップロードする際に、メタデータをデータベースに保存する処理を追加します。

以下は、その例です。

@app.route('/upload', method='POST')
def upload_image():
    upload = request.files.get('image')
    if upload:
        save_path = os.path.join(UPLOAD_DIR, upload.filename)
        upload.save(save_path)  # 画像を保存
        # データベースにメタデータを保存
        conn = sqlite3.connect('files.db')
        c = conn.cursor()
        c.execute("INSERT INTO files (filename) VALUES (?)", (upload.filename,))
        conn.commit()
        conn.close()
        return f"画像 '{upload.filename}' がアップロードされ、データベースに保存されました。"
    return "エラー: 画像がアップロードされませんでした。"

このコードでは、画像を保存した後に、データベースにファイル名を挿入しています。

ファイルのパスをデータベースに保存する方法

ファイルのパスをデータベースに保存することで、後からファイルを簡単に取得できるようになります。

以下は、ファイルのパスをデータベースに保存するためのコードの例です。

@app.route('/upload', method='POST')
def upload_image():
    upload = request.files.get('image')
    if upload:
        save_path = os.path.join(UPLOAD_DIR, upload.filename)
        upload.save(save_path)  # 画像を保存
        # データベースにメタデータとパスを保存
        conn = sqlite3.connect('files.db')
        c = conn.cursor()
        c.execute("INSERT INTO files (filename) VALUES (?)", (save_path,))
        conn.commit()
        conn.close()
        return f"画像 '{upload.filename}' がアップロードされ、データベースに保存されました。"
    return "エラー: 画像がアップロードされませんでした。"

このコードでは、ファイルのパスをデータベースに保存しています。

これにより、後からファイルを簡単に取得できるようになります。

データベースからファイルを取得して表示する方法

データベースに保存されたファイルの情報を取得し、表示するためのルーティングを設定します。

以下は、データベースからファイルを取得して表示するためのコードの例です。

@app.route('/files')
def list_files():
    conn = sqlite3.connect('files.db')
    c = conn.cursor()
    c.execute("SELECT filename FROM files")
    files = c.fetchall()
    conn.close()
    file_list = "<h1>アップロードされたファイル</h1><ul>"
    for file in files:
        file_list += f"<li><a href='/images/{os.path.basename(file[0])}'>{os.path.basename(file[0])}</a></li>"
    file_list += "</ul>"
    return file_list

このコードでは、データベースからファイル名を取得し、リストとして表示しています。

各ファイル名は、画像を表示するためのリンクとして表示されます。

ユーザーがリンクをクリックすると、アップロードされた画像が表示されます。

これにより、ユーザーはアップロードしたファイルを簡単に管理し、表示することができるようになります。

まとめ

この記事では、Bottleを使用したファイルアップロードの実装方法から、複数ファイルのアップロード、画像ファイルのアップロードと表示、さらにはアップロードされたファイルのメタデータをデータベースに保存する方法まで、幅広く解説しました。

これにより、Bottleを活用したWebアプリケーションの開発において、ファイルの取り扱いに関する具体的な手法を身につけることができるでしょう。

今後は、実際に自分のプロジェクトにこれらの技術を応用し、より便利で使いやすいアプリケーションを作成してみてください。

関連記事

Back to top button