Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonでファイルアップロードを実装する方法|HTMLフォームとCGIスクリプトの基本

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

Webブラウザからサーバーへファイルをアップロードするには、HTMLフォームのenctype属性をmultipart/form-dataに設定する必要があります。この指定により、フォームデータが通常のテキストではなくバイナリ形式で送信されるようになります。また、type="file"を指定したinputタグを配置すると、「参照(Browse)」ボタンが表示され、ユーザーがローカル環境からファイルを選択できるようになります。

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

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

<html>
<body>
   <form enctype = "multipart/form-data" action = "save_file.py" method = "post">
   <p>File: <input type = "file" name = "filename" /></p>
   <p><input type = "submit" value = "Upload" /></p>
</form>
</body>
</html>

フォームのaction属性には、アップロード処理を担当するサーバー側スクリプト(ここでは save_file.py)を指定します。

表示結果

上記のコードを実行すると、次のようなフォーム画面が表示されます。

Pythonでファイルアップロードを実装する方法|HTMLフォームとCGIスクリプトの基本

※このサンプルは、当サイトのサーバーへ不特定多数のファイルがアップロードされることを防ぐため、意図的に無効化しています。実際の動作を確認する際は、ご自身のサーバー環境でお試しください。

アップロード処理スクリプト(save_file.py)

続いて、アップロードされたファイルを受け取り、サーバー上に保存するためのPythonスクリプト「save_file.py」を紹介します。

#!/usr/bin/python
import cgi, os
import cgitb; cgitb.enable()

form = cgi.FieldStorage()

# ファイル名を取得する
fileitem = form['filename']

# ファイルがアップロードされたかどうかを確認
if fileitem.filename:
   # ディレクトリトラバーサル攻撃を防ぐため、
   # ファイル名から先頭のパス部分を取り除く
   fn = os.path.basename(fileitem.filename)
   open('/tmp/' + fn, 'wb').write(fileitem.file.read())
   message = 'ファイル "' + fn + '" は正常にアップロードされました'
else:
   message = 'ファイルがアップロードされていません'

print """\
Content-Type: text/html\n
<html>
<body>
   <p>%s</p>
</body>
</html>
""" % (message,)

コードのポイント

  • cgi.FieldStorage():POSTで送信されたフォームデータを取得します。
  • os.path.basename():ファイル名からディレクトリ部分を除去し、ディレクトリトラバーサル攻撃などのセキュリティリスクを回避します。
  • "wb"モード:画像などのバイナリファイルも正しく保存できるよう、バイナリ書き込みモードでファイルを開いています。

OSによるパス区切り文字の違いに注意

上記のスクリプトをUnix/Linux環境で実行する場合は、Windows由来のパス区切り文字(\)に対応させるため、次のようにファイル名を置換してから渡す必要があります。一方、Windowsマシンではそのままのopen()文でも問題なく動作します。

fn = os.path.basename(fileitem.filename.replace("\\", "/" ))

補足:現代的な代替手法について

ここで紹介したcgiモジュールは、Python 3.11で非推奨となり、Python 3.13で標準ライブラリから削除されました。現在の開発では、FlaskやDjangoといったWebフレームワークを使用するのが一般的です。たとえばFlaskなら、わずか数行のコードで同等の処理を実現できます。

from flask import Flask, request

app = Flask(__name__)

@app.route('/upload', methods=['POST'])
def upload():
   f = request.files['filename']
   f.save('/tmp/' + f.filename)
   return 'アップロードが完了しました'

なお、本番環境で運用する場合は、ファイル名のサニタイズ、アップロードサイズの制限、保存先ディレクトリの適切な権限設定など、セキュリティ対策を必ず併せて実施してください。

  1. Pythonのファイルオブジェクトとは?open関数によるファイル操作の基本を徹底解説

    Pythonでは、ファイルを読み書きする際に特別なライブラリをインポートする必要はありません。ファイル操作は言語にネイティブに組み込まれているためです。 まず最初に行うのは、組み込み関数 open() を使ってファイルオブジェクトを取得することです。open() 関数はファイルを開き、ファイルオブジェクトを返します。このファイルオブジェクトには、開いたファイルから情報を取得したり、内容を操作したりするためのメソッドや属性が含まれています。 ファイルとは何か? ファイル操作を行う前に、「ファイルとは何か」を理解しておきましょう。ファイルとは、関連する情報を保存するためにディスク上に確保された「名

  2. 【Python】ジャンクファイルオーガナイザーで面倒なファイル整理を一括自動化

    はじめに 大量のファイルやフォルダをひとつのディレクトリに放り込みっぱなしにして、「何のファイルがあったんだっけ?」と混乱しがちなPythonプログラマーは少なくありません。そんな「怠惰(=効率重視)」な開発者にとって、手作業でのファイル整理は面倒この上ないものです。 そこで本記事では、散らかったフォルダ内のファイルを拡張子ごとに適切なフォルダへ一括で振り分け、さらに不要になった空のディレクトリまで削除してくれるPythonスクリプトを紹介します。コマンドひとつでフォルダがすっきり片付くので、ぜひ活用してみてください。 具体的には、さまざまな種類のファイルが混在したディレクトリ(下図)を入力と