サーチ…


構文

  • request.files ['name']#単一の必須ファイル
  • request.files.get( 'name')#投稿されていない場合はNone
  • request.files.getlist( 'name')#投稿された0個以上のファイルのリスト
  • CombinedMultiDict((request.files、request.form))#フォームとファイルのデータを結合する

ファイルのアップロード

HTMLフォーム

  • fileタイプの入力を使用すると、ブラウザはアップロードするファイルを選択できるフィールドを提供します。
  • postメソッドを持つフォームだけがファイルデータを送信できます。
  • フォームのenctype=multipart/form-data属性を設定してください。それ以外の場合、ファイルの名前は送信されますが、ファイルのデータは送信されません。
  • 単一フィールドに複数のファイルを選択できるようにするには、入力のmultiple属性を使用します。
<form method=post enctype=multipart/form-data>
    <!-- single file for the "profile" field -->
    <input type=file name=profile>
    <!-- multiple files for the "charts" field -->
    <input type=file multiple name=charts>
    <input type=submit>
</form>

Pythonリクエスト

Requestsは、HTTPリクエストを作成するための強力なPythonライブラリです。ブラウザ(または他のツール)を使用して、ブラウザなしでファイル投稿することができます

  • バイナリモードで読み込むファイルを開きます。
  • filesは複数のデータ構造がありfiles 。これは、上記のような複数のファイルを可能にする(name, data)タプルのリストを示しています。
import requests

with open('profile.txt', 'rb') as f1, open('chart1.csv', 'rb') as f2, open('chart2.csv', 'rb') as f3:
    files = [
        ('profile', f1),
        ('charts', f2),
        ('charts', f3)
    ]
    requests.post('http://localhost:5000/upload', files=files)

これは網羅的なリストではありません。好きなツールやもっと複雑なシナリオを使った例については、そのツールのドキュメントを参照してください。

サーバー上のアップロードを保存する

アップロードされたファイルは、 request.filesで利用できます。これは、 MultiDictマッピングフィールド名で、ファイルオブジェクトです。複数のファイルが同じフィールド名でアップロードされた場合は、 []またはget代わりにgetlist使用します。

request.files['profile']  # single file (even if multiple were sent)
request.files.getlist('charts')  # list of files (even if one was sent)

request.filesのオブジェクトには、ファイルをローカルに保存するsaveメソッドがあります。ファイルを保存する共通ディレクトリを作成します。

filename属性は、ファイルがアップロードされた名前です。これは、クライアントが任意に設定できるので、 secure_filenameメソッドに渡して、有効な安全な名前を生成して保存します。 これは、名前が一意であることを保証するものではないため、既存のファイルを検出するために余分な作業をしない限り、既存のファイルは上書きされます。

import os
from flask import render_template, request, redirect, url_for
from werkzeug import secure_filename

# Create a directory in a known location to save files to.
uploads_dir = os.path.join(app.instance_path, 'uploads')
os.makedirs(uploads_dir, exists_ok=True)

@app.route('/upload', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST':
        # save the single "profile" file
        profile = request.files['profile']
        profile.save(os.path.join(uploads_dir, secure_filename(profile.filename)))

        # save each "charts" file
        for file in request.files.getlist('charts'):
            file.save(os.path.join(uploads_dir, secure_filename(file.name)))

        return redirect(url_for('upload'))

    return render_template('upload.html')

WTFormsとFlask-WTFにデータを渡す

WTFormsは、ファイルタイプの入力をレンダリングするためにFileFieldを提供します。アップロードしたデータには特別なことはありません。しかし、Flaskはフォームデータ( request.form )とファイルデータ( request.files )を分割するため、フォームの作成時に正しいデータを渡す必要があります。 CombinedMultiDictを使用して、WTFormsが理解できる単一の構造に2つを組み合わせることができます。

form = ProfileForm(CombinedMultiDict((request.files, request.form)))

FlaskとWTFormを統合する拡張機能であるFlask-WTFを使用している場合、正しいデータを渡すと自動的に処理されます。

WTFormのバグにより、複数のファイルがアップロードされた場合でも、各フィールドには1つのファイルしか存在しません。詳細については、 この問題を参照してください。これは3.0で修正される予定です。

パースCSVファイルは、保存なしでフラッシュ上の辞書のリストとしてアップロードされます

開発者は、ユーザーがCSVファイルをアップロードできるWebサイトを設計する必要があることがよくあります。通常、実際のCSVファイルを保存する理由はありません 。アップロードされると、データは処理され、データベースに保存されるからです。しかし、ほとんどではないにせよ、多くの場合、PYTHONのCSVデータ解析方法では、データをファイルとして読み込む必要があります。 Web開発にFLASKを使用している場合、これは少し頭痛を呈します。

CSVにヘッダー行があり、次のようになっているとします。

h1,h2,h3
'yellow','orange','blue'
'green','white','black'
'orange','pink','purple'

今、ファイルをアップロードするhtmlフォームが次のようになっているとします。

<form action="upload.html" method="post" enctype="multipart/form-data">
    <input type="file" name="fileupload" id="fileToUpload">
    <input type="submit" value="Upload File" name="submit">
</form>

誰もあなたの車輪を再発明したくないので、あなたはあなたのFLASKスクリプトにcsvをインポートすることに決めました。人々が正しい順序で列を含むcsvファイルをアップロードするという保証はありません。 csvファイルにヘッダー行がある場合は、 csv.DictReaderメソッドの助けを借りて、CSVファイルをヘッダー行のエントリーでキー入力して辞書のリストとして読み取ることができます。しかし、 csv.DictReaderはファイルを必要とし、文字列を直接受け入れません。アップロードされたファイルを最初に保存し、新しいファイル名と場所を取得しcsv.DictReaderを使用してファイルを開き 、ファイルを削除するには、 FLASKメソッドを使用する必要があると考えるかもしれません。少し浪費のようです。

幸いなことに、ファイルの内容を文字列として取得し、文字列を終端された行で分割することができます。 csvメソッドcsv.DictReaderはこれをファイルの代用として受け入れます。次のコードは、ファイルを一時的に保存せずにこれを実行する方法を示しています。

@application.route('upload.html',methods = ['POST'])
def upload_route_summary():
    if request.method == 'POST':

        # Create variable for uploaded file
        f = request.files['fileupload']  

        #store the file contents as a string
        fstring = f.read()
        
        #create list of dictionaries keyed by header row
        csv_dicts = [{k: v for k, v in row.items()} for row in csv.DictReader(fstring.splitlines(), skipinitialspace=True)]

        #do something list of dictionaries
    return "success"

変数csv_dictsは次の辞書のリストになりました:

   csv_dicts = 
    [
        {'h1':'yellow','h2':'orange','h3':'blue'},
        {'h1':'green','h2':'white','h3':'black'},
        {'h1':'orange','h2':'pink','h3':'purple'}
    ]

PYTHONを初めてお使いの場合は、次のようなデータにアクセスできます:

csv_dicts[1]['h2'] = 'white'
csv_dicts[0]['h3'] = 'blue'

その他のソリューションには、 ioモジュールのインポートとio.Streamメソッドの使用が含まれます。私はこれがもっと簡単なアプローチだと感じています。私はコードがioメソッドを使うより少し簡単だと信じています。この方法は、アップロードされたCSVファイルを解析する例に固有です。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow