multipart/form-data でファイルを POST する
以下の例では、画像、csvファイルをPOST
workspace/templates/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>API Sample</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
<input name="user-file" type="file" accept="image/png, image/jpeg, .csv">
<button type="submit">submit</button>
</form>
</body>
</html>
accept:ファイルを選ぶ時のフィルターで、何かを制限するものではない。(特に指定しなくてもいい)
workspace/server.py
from flask import Flask, render_template, jsonify, request
import numpy as np
import pandas as pd
import mimetypes
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/upload', methods=['POST'])
def upload():
file = request.files['user-file']
if not file: return jsonify(message='no file!')
extension = mimetypes.guess_extension(file.content_type)
print("extension:", extension)
if extension == '.csv': //★★★
df = pd.read_csv(file)
print(df)
return jsonify(message='csv!')
elif extension == '.png' or extension == '.jpeg':
stream = file.stream
img_array = np.asarray(bytearray(stream.read()), dtype=np.uint8)
return jsonify(message='image!')
return jsonify(message='no support file!')
if __name__ == '__main__':
app.run(debug=True)
★★★:
csvファイルは、mimetypeが「text/csv」となるはずだが、chromeでは「application/octet-stream」となる。
「application/octet-stream」は、ファイルタイプが不明な場合のmimetype。
ただし、pandasでdataframeとして読み込むことはできる。
- 参考
よくある MIME タイプ
Python, mimetypesでMIMEタイプをファイル名(拡張子)から推定
- エラー回避
VSCodeでデバッグするときの設定
PyCharm、VSCodeなどを使用している場合、ブレークポイントでコードをステップ実行できます。
.py
app.run(debug=True, use_reloader=False)
- 参考