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

10887 ワード

Flaskファイルのアップロード
  • Flaskアップロードファイル
  • アップロードを改善
  • アップロードプログレスバー
  • より簡便なスキーム

  • ファイルアップロードの基本原理は実際には簡単ですが、基本的には:
  • enctype=multipart/form-dataを有する タグであり、タグにはが含まれている.
  • アプリケーションは、要求されたオブジェクトのfiles辞書によってファイルにアクセスする.
  • ファイルのsave()メソッドを使用して、ファイルシステムにファイルを永続的に保存します.

  • 例、アップロードファイルhtmlページ:
    <form action="" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <input type="file" name="img">
        <input type="submit" value="  ">
    form>

    基本的なアプリケーションから始めましょう.このアプリケーションは指定したディレクトリにファイルをアップロードし、ユーザーにファイルを表示します.
    以下に、適用するプリアンブルを示します.
    import os,sys
    from flask import Flask, flash, request, redirect, url_for
    from werkzeug.utils import secure_filename
    
    #       ,          os            windows              ,
    #       uploads,              。
    UPLOAD_FOLDER =os.path.curdir+os.path.sep+'uploads'+os.path.sep
    ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])
    
    app = Flask(__name__)
    app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

    まず、私たちは多くのものを導入しました.多くは分かりやすいです.werkzeug.secure_filename()は後で説明します.UPLOAD_FOLDERはファイルをアップロードするために格納されるディレクトリであり、ALLOWED_EXTENSIONSはアップロードを許可するファイル拡張子の集合である.
    注意:移行を容易にするために、ファイルをアップロードするパスはosモジュールを使用して、現在のフォルダのwindowsファイル区切り記号を探して、本当のディレクトリ名を接続します.例えば私のはuploadsで、最後にファイル区切り記号を追加すればいいです.
    python os.path    :
    
    os.path.sep -->windows      
    os.path.altsep -->linux   :'/' 
    
       :os.path.curdir
        :os.path.pardir
       :os.path.abspath(path)
        :os.path.join()
    
           :os.path.split(path), path           ,     。
  • なぜファイルの拡張子を制限するのですか?

  • クライアントに直接データを送信すると、ユーザーに任意のファイルをアップロードさせたくない場合があります.そうでなければ、XSSの問題を引き起こす可能性があるため、ユーザーがHTMLファイルをアップロードできないことを確認する必要があります(クロスステーションスクリプト攻撃(XSSを参照).サーバがPHPファイルを実行できる場合は、.phpファイルのアップロードが許可されていないことを確認する必要があります.
    次の関数は、拡張子が正当かどうかをチェックし、ファイルをアップロードし、アップロードされたファイルのURLにユーザーをリダイレクトします.
    def allowed_file(filename):
        #        , '.'           
        return '.' in filename and \
            filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
    
    @app.route('/', methods=['GET','POST'])
    def upload_file():
        if request.method == 'POST':
            # check if the post request has the file part
            if 'file' not in request.files:
                flash('No file part')
                return redirect(request.url)
            file = request.files['file']
            #         ,                   
            if file.filename == '':
                flash('No selected file')
                return redirect(request.url)
            #              
            if file and allowed_file(file.filename):
               filename = secure_filename(file.filename)
               #         
               file.save(os.path.join(app.config['UPLOAD_FOLDER'],filename))
               #          URL
               return redirect(url_for('uploaded_file', filename=filename))
        return '''
        
        Upload new File
        

    Upload new File

    '''

    では、secure_filename()関数はいったい何の役に立つのでしょうか.
    「ユーザー入力を信頼しない」という原則があります.
    この原則は、アップロードされたファイルのファイル名にも適用されます.提出されたフォームデータはすべて偽造されている可能性があります.ファイル名も危険です.この場合、ファイルシステムにファイルを保存する前に、常にsecure_filenameという関数を使用してファイル名をセキュリティチェックすることを忘れないでください.
    さらに説明するsecure_filename()でどのような仕事をしたのか、使用しないとどうなるのかを知ることができます.次の情報をfilenameとしてあなたに伝える人がいるとします.
    filename = "../../../../home/username/.bashrc"
    ../の数が正しいと仮定すると、UPLOAD_とFOLDERが結合すると、ユーザーはサーバ上のファイルを修正する能力があり、このファイルはもともとユーザーが修正する権利がありません.これはアプリケーションがどのように動作しているかを知る必要がありますが、私を信じてください.ハッカーは変態です.
    関数がどのように機能しているかを見てみましょう.
    >>> secure_filename('../../../../home/username/.bashrc')
    'home_username_.bashrc'

    アップロードされたファイルにサービスを提供することが残っています.upload_file()では、ユーザをurl_for('uploaded_file', filename=filename)、すなわち/uploads/filenameにリダイレクトする.
    したがって、uploaded_file()を書いてファイル名を返します.
    Flask 0.5リリースでは、このタスクを完了するために関数を使用できます.
    from flask import send_from_directory
    
    @app.route('/uploads/')
    def uploaded_file(filename):
        return send_from_directory(app.config['UPLOAD_FOLDER'],
                                   filename)

    また、uploaded_fileはbuild_として登録されていますonlyルールは、SharedDataMiddlewareを使用します.
    この方法はFlaskの古いバージョンで使用できます.
    from werkzeug import SharedDataMiddleware
    app.add_url_rule('/uploads/', 'uploaded_file',
                     build_only=True)
    app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
        '/uploads':  app.config['UPLOAD_FOLDER']
    })

    アプリケーションを現在実行している場合は、すべてが予想通りに正常に動作する必要があります.
    注意しなければならないのは、現在適用されている下で、あなたがアップロードした画像ファイルの名前は英語です.中国語では、保存するか開くかを尋ねる弾枠が出てきますが・・・
    アップロードの改善
    Flaskはファイルのアップロードをどのように処理しているのでしょうか.
  • アップロードされたファイルが小さい場合は、メモリに保存されます.
  • でなければ、一時的な位置に保存されます(tempfile.gettempdir()でこの位置が得られます).

  • アップロードファイルのサイズを制限するにはどうすればいいですか?
    デフォルトでは、Flaskはアップロードファイルのサイズを制限しません.構成のMAX_CONTENT_LENGTHを設定することで、ファイルサイズを制限できます.
    from flask import Flask, Request
    
    app = Flask(__name__)
    app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

    上のコードはサイズを16 Mに制限します.このサイズより大きいファイルがアップロードされると、FlaskはRequestEntityTooLargeの異常を放出します.
    接続リセットの問題
    ローカル開発サーバを使用すると、413応答ではなく接続がリセットされる可能性があります.本番WSGIサーバでアプリケーションを実行すると、適切な応答が得られます.
    この機能はFlask 0.6バージョンに追加されています.ただし、リクエストオブジェクトを継承することで、古いバージョンでもこの機能を実現できます.詳細については、Werkzeugのファイル処理に関するドキュメントを参照してください.
    進捗バーのアップロード
    少し前までは、多くの開発者がアップロードの進捗バーを実現していました.ブロック化してアップロードされたファイルを読み取り、データベースにアップロードの進捗を格納し、クライアントでJavaScriptを通じて進捗を取得しました.簡単に言えば、クライアントは5秒ごとにサーバにアップロードの進捗状況を尋ねます.皮肉だと思いますか?クライアントは知っていることを知っている.
    より簡単なシナリオ
    より迅速かつ信頼性の高いソリューションが提供されました.jQueryのようなJavaScriptライブラリに含まれる、簡単にプログレスバーを構築できるプラグイン.
    すべてのアプリケーションでファイルをアップロードするスキームは基本的に同じであるため、Flask-Uploads拡張を使用してファイルアップロードを実現することができます.この拡張は完全なアップロードメカニズムを実現し、ホワイトリスト機能、ブラックリスト機能、その他の機能も備えている.
    鉄楽と猫
    2018-9-6
    リファレンスリファレンス
    Flask公式サイト中国語ドキュメント-アップロードファイル