FlaskのAPIでファイルアップロードを受け付ける方法!初心者でもわかる解説
生徒
「先生、Flaskで写真やPDFを送れるAPIを作りたいです。どうすればいいですか?」
先生
「それなら、Flaskのファイルアップロード機能を使えば簡単につくれます。初心者でも使いやすく説明しますね。」
生徒
「ファイルって難しそうですが、頑張れますか?」
先生
「大丈夫ですよ。今日はアップロードの仕組みや注意点も含めて、やさしく丁寧に解説します。」
1. ファイルアップロードってなに?
ファイルアップロードとは、ユーザーが自分のパソコンやスマホから、画像・PDF・文章ファイルなどをWebアプリへ送るしくみのことです。たとえばSNSで写真を投稿したり、学校や会社に書類を提出したりする場面で自然と使われています。
Web APIの場合は、送られてきたファイルをサーバー側が受け取り、保存したり、内容を解析したり、別の処理につなげたりできます。つまり「ユーザーが送ったものを、サーバーが受け取って次の処理に回すための入り口」がファイルアップロードです。
アップロードの流れをよりイメージしやすくするために、ユーザーがファイルを選んで送る場面を簡単な例で見てみましょう。
[ユーザーが実行する動きのイメージ]
1. 「ファイルを選択」ボタンを押す
2. 写真やPDFを選ぶ
3. サーバーへ送信(アップロード)
4. サーバー側が受け取り、保存や処理を開始
このように、ファイルアップロードはとても身近な機能であり、Flaskでも少ないコードで実装できます。次の項目から、実際にどのように受け取るのかを一緒に見ていきましょう。
2. Flaskとは?初心者向けのやさしい復習
Flask(フラスク)は、Pythonというプログラミング言語でWebアプリやWeb APIを作るためのフレームワーク(道具のセット)です。難しい設定をいきなり覚えなくても、「このURLにアクセスされたら、この処理を実行する」といった基本から始められるので、プログラミング未経験の人でも学びやすいのが大きな特徴です。
イメージとしては、Pythonが「言葉」だとしたら、Flaskはその言葉を使ってWebサイトやファイルアップロードAPIを組み立てるための「簡単な設計図」といったところです。必要最低限の機能だけが用意されているので、自分のやりたいことに合わせて、少しずつ機能を足しながら学んでいけます。
雰囲気をつかむために、まずはとてもシンプルなFlaskアプリの例を見てみましょう。ここではファイルアップロードではなく、「ページに文字を表示するだけ」の最小構成です。
from flask import Flask
app = Flask(__name__) # アプリ本体を作る
@app.route("/")
def hello():
return "こんにちは、Flaskの世界へようこそ!"
if __name__ == "__main__":
app.run(debug=True)
このサンプルでは、Flask(__name__) でアプリを用意し、@app.route("/") で「ブラウザで / にアクセスされたらこの関数を実行してね」というルール(ルーティング)を決めています。実行すると、ブラウザには文字列がそのまま表示されます。
今回の記事で扱う「ファイルアップロードAPI」も、この基本形の延長線上にあります。先ほどのような小さなFlaskアプリに、ファイルを受け取るための処理を追加していくことで、画像やPDFをサーバー側に送信・保存できるようになります。次の項目から、具体的にファイルアップロードを受け取るコードを見ていきましょう。
3. ファイルアップロードを受け取るFlaskのコード
ここからは、実際にFlaskでファイルアップロードを受け付けるAPIエンドポイントを作ってみましょう。まずは「サーバーがファイルを受け取って、ローカルのフォルダに保存する」シンプルなパターンです。ファイルアップロードAPIの基本的な流れをつかむことが目的なので、できるだけ短く分かりやすいコードにしています。
次のサンプルでは、/upload というURLに対して画像やPDFファイルを送ると、uploads フォルダに保存し、「アップロード成功」というメッセージをJSONで返すようにしています。ファイルアップロードの入り口となる典型的な例だと思ってください。
from flask import Flask, request, jsonify
import os
app = Flask(__name__)
# ファイルを保存するフォルダを設定
app.config['UPLOAD_FOLDER'] = 'uploads'
# ファイルアップロード用のAPIエンドポイント
@app.route('/upload', methods=['POST'])
def upload():
# フォームの中に "file" という名前のデータがあるか確認
if 'file' not in request.files:
return jsonify({'error': 'ファイルが見つかりません'}), 400
file = request.files['file']
# ファイル名が空(何も選ばれていない)場合のチェック
if file.filename == '':
return jsonify({'error': 'ファイル名が空です'}), 400
# 保存先のパスを組み立てて実際に保存
filepath = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
file.save(filepath)
# 正常に保存できたらメッセージを返す
return jsonify({'message': 'アップロード成功', 'filename': file.filename}), 200
if __name__ == '__main__':
# 保存用フォルダがなければ自動で作成
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
# 開発用サーバーを起動
app.run(debug=True)
このコードを app.py として保存し、ターミナルから python app.py を実行すると、ローカル環境でFlaskの開発サーバーが立ち上がります。あとは別のツールやフォームから /upload に向けてファイルを送信すれば、uploads フォルダに画像やPDFが保存され、「アップロード成功」というJSONレスポンスが返ってきます。どの部分が「ファイルを受け取り」「どこで保存しているのか」は、次の項目でゆっくり分解して確認していきましょう。
4. どうやって動いているの?初心者向けに解説
ここでは、ひとつ前の章で出てきたFlaskのファイルアップロードAPIが「どんな順番で動いているのか」を、プログラミング未経験の人向けにやさしく分解してみます。難しい言葉はできるだけ避けて、「サーバーが何をしているのか」という流れをイメージできるようにしていきましょう。
① request.files:サーバーに届いた荷物が入る箱
request.files は、「ユーザーがアップロードしたファイル」が入っている特別な箱のようなものです。FlaskのファイルアップロードAPIでは、ブラウザやcurlから送られてきた画像・PDFなどのファイルが、この request.files の中に入ってサーバーに届きます。
たとえばフォーム側で name="file" として送ると、Pythonのコードでは request.files['file'] と書くことで、そのファイルを取り出せます。「荷物置き場(request.files)の中から、file というラベルが付いた荷物を取り出す」というイメージです。
② UPLOAD_FOLDER:ファイルをしまっておく棚の場所
UPLOAD_FOLDER は、「アップロードされたファイルをどのフォルダに保管するか」を決めるための設定です。記事のサンプルコードでは、app.config['UPLOAD_FOLDER'] = 'uploads' と書いて、アプリの中で「uploads というフォルダに保存しようね」と約束しています。
現実の世界でいうと、「荷物が届いたら、この棚(uploads フォルダ)に片づけておいてね」と指示しているようなイメージです。Flaskのアプリ側であらかじめ場所を決めておくことで、どこにファイルが保存されるのかが分かりやすくなります。
③ file.save():実際に棚へ置く(保存する)動き
file.save() は、「取り出したファイルを実際にパソコンの中へ保存する」ための命令です。先ほどの request.files['file'] で取り出したファイルオブジェクトに対して、file.save(保存先のパス) と書くと、PythonとFlaskがファイルを指定のフォルダへ書き込んでくれます。
サンプルコードでは、os.path.join(app.config['UPLOAD_FOLDER'], file.filename) で「uploads フォルダ + ファイル名」をくっつけて保存先のパスを作り、そのパスを file.save() に渡していました。これが、Flaskのファイルアップロードで「実際にディスクへ保存している部分」です。
④ エラー時は400番台で丁寧にお知らせ
ファイルアップロードAPIでは、次のような「よくある失敗パターン」をチェックしています。
- request.files に "file" が入っていない(そもそもファイルが送られていない)
- file.filename が空文字(ファイルが選択されていない)
こうした場合は、jsonify({'error': 'ファイルが見つかりません'}) のようにエラーメッセージと一緒に、400(Bad Request)というHTTPステータスコードを返しています。「リクエスト(お願い)の内容が間違っているので、もう一度正しい形で送ってくださいね」というサインだと思ってください。
⑤ 全体の流れをざっくりおさらい
[FlaskファイルアップロードAPIの流れイメージ]
1. ユーザーが画像やPDFを選んで送信する
2. Flaskがリクエストを受け取り、request.files にファイルが入る
3. "file" という名前でファイルを取り出す
4. UPLOAD_FOLDER を使って保存先のパスを作る
5. file.save() でパソコンのフォルダに保存する
6. 成功したら「アップロード成功」というJSONを返す
7. 失敗したら 400 エラーとエラーメッセージを返す
このように、FlaskのファイルアップロードAPIは「届いたファイルを箱から取り出し、保存場所を決めて、棚にしまい、結果を返す」というシンプルな流れで動いています。仕組みのイメージがつかめてきたら、次の章で自分の環境からファイルを送ってみて、実際にアップロードが成功するか試してみましょう。
5. curlでファイルアップロードを試してみよう
ターミナルで以下のように入力すると、APIに画像やファイルを送れます。
curl -F "file=@path/to/ファイル.png" http://localhost:5000/upload
実行すると次のような応答が返ってきます:
{"message":"アップロード成功","filename":"ファイル.png"}
6. セキュリティと注意点
ファイルを受け取るときは、次のような点に注意しましょう:
- ファイル名に悪意ある文字(../../など)がないか確認する
- ファイルサイズが大きすぎないかチェック(上限を決める)
- アップロード先のフォルダにアクセス権限を設定する
これらを守ることで、予期せぬ問題を防ぐことができます。
7. Flask拡張で便利にする方法:Flask‑Uploads など
Flaskにはファイルアップロードを簡単にする拡張(エクステンション)がいくつかあります。
たとえばFlask‑Uploadsを使うと、ファイル保存のルールをまとめて設定できます。ただし、今回はコードをシンプルに保つため使いませんでした。
8. 初心者でもできる応用例:画像サイズをチェックする
簡単な応用として、アップロードされた画像の大きさ(サイズ)や幅・高さを調べて、条件に合わなければ返す方法もあります。
たとえばPillowという画像処理ライブラリを使えば、サムネイルを作ったりリサイズしたりもできます。
まとめ
Flaskでファイルアップロードを受け付けるAPIをつくる流れを振り返ると、最初はむずかしく感じる部分があっても、仕組みを順番に追っていくことで自然と理解できることがわかります。とくに、画像やPDFのアップロードはWeb開発で頻繁に登場する操作であり、フロントエンドとバックエンドのやりとりを実感できる良い題材になります。Flaskのrequest.filesを使う基本の処理や、ファイル保存のためのフォルダ設定、そしてエラーハンドリングなどは、シンプルでありながら大きな意味を持つポイントでした。実際の現場でも、ユーザーが安心してアップロードできる仕組みづくりには丁寧なチェックが欠かせません。
ファイルアップロードAPIを扱う際には、「どんなファイルが送られてくるかわからない」という前提で考えることが重要になります。たとえば、存在しないファイルを送られた場合にどう返すか、ファイル名が空だった場合にどう判断するのか、意図しないパスを渡されても安全に扱えるようにするには何が必要なのかといった細かな配慮が求められます。今回の記事で扱った400エラーの返し方や安全なフォルダの指定は、初歩の段階でも身につけておきたい基本の習慣です。こうした細部の安全対策は、アプリの信頼性を大きく左右します。
また、Flaskの基本的なファイル保存に加えて、初心者でも挑戦できる応用として画像の判定や加工などもありました。とくに画像処理ライブラリであるPillowを組み合わせると、アップロードされた画像から幅や高さを取得したり、サムネイルを作成したりといった柔軟な機能を簡単に実装できます。こうした処理は日常的なWebサービスでもよく見られるため、学んでおくと実用的なアプリづくりへの一歩が大きく前進します。ファイルアップロードが理解できると、フォーム投稿、プロフィール画像管理、証明書アップロード管理など多くの機能が自分の手で作れるようになります。
さらに、curlでの動作確認方法を通じて、「ブラウザ以外からAPIを試す」という開発の基礎も理解できました。API開発では、ユーザーの画面から送られるリクエストを直接確認する場面が多く、こうしたシンプルな検証方法の習得は非常に役立ちます。慣れてくると、ブラウザの開発者ツールやPostmanなどを使った検証にも自然と挑戦できるでしょう。ファイルアップロードAPIは「送る」「受け取る」「保存する」という動きが明確なため、APIのしくみを理解するための題材として最適です。
最後に、ファイルアップロードの基本部分をあらためて整理したサンプルプログラムを示します。記事全体で学んだ内容をまとめた例として、自分のプロジェクトにも応用しやすい形になっています。安全にファイルを扱いながら、必要に応じて機能を追加したり、拡張ライブラリを試してみたりと、学びを積み重ねていくきっかけにしてもらえると嬉しいです。
サンプルプログラムで復習しよう
以下は記事内容を踏まえた、より丁寧なチェックを追加した例です。
from flask import Flask, request, jsonify
import os
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024 # 5MB制限
ALLOWED_EXT = {'png', 'jpg', 'jpeg', 'pdf'}
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXT
@app.route('/safe-upload', methods=['POST'])
def safe_upload():
if 'file' not in request.files:
return jsonify({'error': 'ファイルがありません'}), 400
file = request.files['file']
if file.filename == '':
return jsonify({'error': 'ファイル名が空です'}), 400
if not allowed_file(file.filename):
return jsonify({'error': '許可されていない形式です'}), 400
filename = secure_filename(file.filename)
path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(path)
return jsonify({'message': '安全にアップロードできました', 'filename': filename}), 200
if __name__ == '__main__':
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
app.run(debug=True)
このプログラムでは、ファイル形式のチェックやサイズ制限、名前の安全化など、実際のサービスで必要になる機能が含まれています。こうしたポイントを押さえることで、ユーザーが安心して使えるAPIに一歩近づきます。ファイル機能は範囲が広いように見えますが、着実に理解していけば必ず扱えるようになるので、引き続き楽しみながら学んでみてください。
生徒
「まとめて見直してみると、ファイルアップロードって単純に保存するだけじゃなくて、安全に扱う工夫がたくさん必要なんですね。」
先生
「そうですね。アップロード機能は便利な反面、油断するとリスクもあります。だからこそ、正しくチェックしたり、安全なやり方に気を配る姿勢が大切なんです。」
生徒
「今回のコードがあれば、画像投稿や資料の提出機能も作れそうです!応用にも挑戦したいです。」
先生
「ぜひ挑戦してください。ファイル機能を理解すると作れるサービスの幅が一気に広がります。次は画像加工やサムネイル生成にも進んでみましょう。」