ことさら−古都プログラマーの更級日記

京都でお寺を回りながら御朱印集めをしていたり、LoLをしたり試合を見に行ったりしているエンジニアのブログです。技術的なはなしとか日常的なはなし、カメラやLoLや競馬の話も書きます。右メニューに検索やらカテゴリーやらがあるので、見たい記事だけ見てね!

curlで複数のファイルとファイル以外のパラメータをPOSTして、PythonのFlaskでそれらを受け取る

f:id:yoshiki_utakata:20171218174621p:plain

curlでファイルをPOSTしてFlaskで受け取る方法

Webアプリ開発中、curlAPIの動作を確認したい時があるかと思います。 先日PythonのWebフレームワーク Flask を使ってWebアプリを開発していたのですが、curlでどうやってpostしたらいいのか、さらにはFlaskでどうやって受け取ったらいいのか悩みました。そこで僕がハマった以下のポイントをまとめていきたいと思います。

  • curlでpostしたパラメータをFlaskで受け取るにはどうしたらいいのか
  • curlでファイルをpostするにはどうしたらいいのか
  • それをどうやってFlaskで受け取るのか
  • curlで2つ以上のファイルをpostするにはどうしたらいいのか
  • どうやってFlaskで受け取るのか、どうやって2つのファイルを区別すればいいのか。
  • curlでファイルをpostしつつ普通のパラメーター(文字列)もpostするにはどうしたらいいのか
  • それらを Python の Web フレームワーク Flask で受けるにはどうしたらいいのか

ということで、以下を説明します。

  • curlでファイルをpostする方法
  • curlで複数個のファイルをpostする方法
  • curlでファイルをpostしつつ文字列のパラメータも渡す方法
  • これをFlaskで受ける方法

curlでファイルをpostする方法

ファイルをPATH指定でpostする時は @ を付けて以下のようにします。

curl -X POST http://localhost:8080/api/images -F image=@resources/1.jpg

image というのがパラメータ名です。

curl でファイルを複数個postする方法

以下のようにpostします。

curl -X POST http://localhost:8080/api/images -F image=@resources/1.jpg -F image_second=@resources/2.jpg

image, image_second というのがパラメータ名で、受け取る側はこの名前でファイルを区別します。

curlでファイルをpostしつつ普通のパラメータもpostする方法

@ を付けないと普通に文字列がそのままパラメータとして送られます。

curl -X POST http://localhost:8080/api/images -F "x=1" -F "y=5" -F  -F image=@resources/1.jpg -F image_second=@resources/2.jpg

x=1&y=5&image=<1.jpgのバイナリ>&image_second=<2.jpgのバイナリ> が送られるイメージです。

これをPythonのFlaskで受ける方法

curl -X POST http://localhost:8080/api/images -F "x=1" -F "y=5" -F  -F image=@resources/1.jpg -F image_second=@resources/2.jpg

これをどうやって Flask で受け取るのか。以下の様に受け取ります。Flaskの説明や、受けた後の処理とかはここでは書きません。受ける方法は以下のとおりです。

from flask import Flask, request

app = Flask(__name__)

@app.route("/api/images", methods=["POST"])
def postImage():
    # 普通のパラメータを受け取る
    x = request.form.get('x', type = int)
    x = request.form.get('y', type = int)

    # ファイルを受け取る FileStorage 型で取得できる
    image = request.files.get('image')
    image_second = request.files.get('image_second')

if __name__ == "__main__":
    port = int(os.environ.get("PORT", 8080))
    app.run(port=port, debug=True)
  • x=1 などの値は、request.form 経由で取得します。 type は int, string などを指定してください。
  • image=@resources/1.jpg こちらは、 request.files で受けとることができます。FileStorage 型という型で返ってきます。image.save('/tmp/image.jpg') などとすることで保存ができたりします。

まとめ

  • curlでファイルをpostするのは -F 名前=@パス
  • パラメータも -F 名前=値 で同時にpostできる
  • Flaskで受け取るのはそれぞれ request.files, request.form

手元で動かしながらデバッグしていたのですが、どうやってデバッグしたらいいのか悩みました。参考にしてみてください。