iMind Developers Blog

iMind開発者ブログ

Flaskでファイルアップロード

概要

FlaskでHTMLフォームからファイルをアップロードしてサーバー上に保存する。

バージョン情報

  • Flask==1.1.1

参考ページ

https://flask.palletsprojects.com/en/1.1.x/patterns/fileuploads/

シンプルなファイルアップロード機能

postされたファイルをファイル保存するだけのシンプルな機能のソースコード。

import flask
app = flask.Flask(__name__)

# フォーム表示
@app.route('/', methods=['GET'])
def index():
    return '''
    <form method="post" action="/upload" enctype="multipart/form-data">
      <input type="file" name="file">
      <button>upload</button>
    </form>
'''

# アップロード機能
@app.route('/upload', methods=['POST'])
def upload():
    if 'file' not in flask.request.files:
        return 'ファイル未指定'

    # fileの取得(FileStorage型で取れる)
    # https://tedboy.github.io/flask/generated/generated/werkzeug.FileStorage.html
    fs = flask.request.files['file']

    # 下記のような情報がFileStorageからは取れる
    app.logger.info('file_name={}'.format(fs.filename))
    app.logger.info('content_type={} content_length={}, mimetype={}, mimetype_params={}'.format(
        fs.content_type, fs.content_length, fs.mimetype, fs.mimetype_params))

    # ファイルを保存
    fs.save('保存するファイルパス')

    return "フィアルアップロード成功"

if __name__ == '__main__':
    app.run(debug=True)

これでfs.saveに指定したファイル名でアップロードしたファイルが保存される。

上記ではsaveを呼び出してファイル保存しているが、テキストであれば下記のように行ループで中身を取得することも可能。

for line in fs:
    print(line)

FileStorage.streamを取るとSpooledTemporaryFileが取れる。

fs.stream

    #=> tempfile.SpooledTemporaryFile

最大ファイルサイズの制限

アップロードされるコンテンツのサイズはMAX_CONTENT_LENGTHで制限できる。下記は16MB。

app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

拡張子チェック

filenameでファイル名が取れるので、取得したファイル名から拡張子のチェックを行う。

import pathlib

ALLOWED_EXTENSIONS = ['.jpg', '.jpeg']

fs = flask.request.files['file']
suffix = pathlib.Path(fs.filename).suffix

if not suffix in ALLOWED_EXTENSIONS:
    return "not allowed extension : {}".format(suffix)

画像形式チェック

画像ファイルがアップロードされる想定の機能で、その形式をチェックするコード。

import imghdr

ALLOWED_TYPES = ['jpeg', 'png']

file_type = imghdr.what(fs.stream)
if not file_type in ALLOWED_TYPES:
    return "not allowed file type : {}".format(file_type)

送信された画像の表示

png画像が送られてくる想定で、読み込んだ画像をbase64でHTMLに埋め込んでみる。

import base64

fs = flask.request.files['file']
img_base64 = base64.b64encode(fs.read())

return '''<img src="data:image/png;base64,{}">'''.format(img_base64)

これでアップロードした画像が画面に表示される。

改定履歴

Author: Masato Watanabe, Date: 2020-01-25, 記事投稿