Ricerca…


Sintassi

  • request.files ['name'] # singolo file richiesto
  • request.files.get ('name') # Nessuno se non pubblicato
  • request.files.getlist ('name') # lista di zero o più file pubblicati
  • CombinedMultiDict ((request.files, request.form)) # combina i dati di forma e file

Caricamento di file

Modulo HTML

  • Utilizza un input di tipo file e il browser fornirà un campo che consente all'utente di selezionare un file da caricare.
  • Solo i moduli con il metodo post possono inviare dati di file.
  • Assicurati di impostare l' enctype=multipart/form-data . Altrimenti verrà inviato il nome del file ma non i dati del file.
  • Utilizzare l'attributo multiple sull'input per consentire la selezione di più file per il singolo campo.
<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>

Richieste Python

Requests è una potente libreria Python per effettuare richieste HTTP. Puoi usarlo (o altri strumenti) per pubblicare file senza browser.

  • Apri i file da leggere in modalità binaria.
  • Ci sono più strutture di dati che i files richiedono. Questo dimostra un elenco di tuple (name, data) , che consente più file come il modulo sopra.
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)

Questo non vuole essere un elenco esaustivo. Per esempi che utilizzano il tuo strumento preferito o scenari più complessi, consulta i documenti per quello strumento.

Salva i caricamenti sul server

I file caricati sono disponibili in request.files , i nomi dei campi di mappatura MultiDict in oggetti file. Utilizza getlist - anziché [] o get - se più file sono stati caricati con lo stesso nome di campo.

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

Gli oggetti in request.files hanno un metodo di save che salva il file localmente. Creare una directory comune in cui salvare i file.

L'attributo filename è il nome con cui è stato caricato il file. Questo può essere impostato arbitrariamente dal client, quindi passarlo attraverso il metodo secure_filename per generare un nome valido e sicuro per salvare come. Ciò non garantisce che il nome sia univoco , quindi i file esistenti verranno sovrascritti a meno che non si eseguano ulteriori operazioni per rilevarlo.

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')

Trasmissione dei dati a WTForms e Flask-WTF

WTForms fornisce un FileField per FileField rendering di un input di tipo di file. Non fa nulla di speciale con i dati caricati. Tuttavia, poiché Flask suddivide i dati del modulo ( request.form ) e i dati del file ( request.files ), è necessario assicurarsi di passare i dati corretti durante la creazione del modulo. Puoi usare CombinedMultiDict per combinare i due in un'unica struttura che WTForms comprende.

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

Se stai usando Flask-WTF , un'estensione per integrare Flask e WTForms, il passaggio dei dati corretti verrà gestito automaticamente.

A causa di un bug in WTForms, sarà presente un solo file per ogni campo, anche se sono stati caricati più file. Vedi questo problema per maggiori dettagli. Sarà corretto in 3.0.

FILE CSV PARSE CARICARE COME ELENCO DEI DIZIONARI IN BANCO SENZA RISPARMIO

Gli sviluppatori spesso devono progettare siti Web che consentano agli utenti di caricare un file CSV. Di solito non vi è alcun motivo per salvare il file CSV effettivo poiché i dati verranno elaborati e / o memorizzati in un database una volta caricati. Tuttavia, molti se non la maggior parte, i metodi PYTHON per analizzare i dati CSV richiedono che i dati vengano letti come un file. Questo potrebbe presentare un po 'di mal di testa se si utilizza FLASK per lo sviluppo web.

Supponiamo che il nostro CSV abbia una riga di intestazione e assomiglia al seguente:

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

Ora, supponiamo che il modulo html per caricare un file sia il seguente:

<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>

Dal momento che nessuno vuole reinventare la ruota, decidi di importare CSV nel tuo script FLASK . Non vi è alcuna garanzia che le persone caricheranno il file csv con le colonne nell'ordine corretto. Se il file csv ha una riga di intestazione, con l'aiuto del metodo csv.DictReader puoi leggere il file CSV come un elenco di dizionari, immesso dalle voci nella riga di intestazione. Tuttavia, csv.DictReader necessita di un file e non accetta direttamente le stringhe. Si potrebbe pensare che sia necessario utilizzare i metodi FLASK per salvare prima il file caricato, ottenere il nuovo nome e il percorso del file, aprirlo utilizzando csv.DictReader e quindi eliminare il file. Sembra un po 'uno spreco.

Fortunatamente, possiamo ottenere il contenuto del file come una stringa e quindi dividere la stringa in righe terminate. Il metodo csv csv.DictReader lo accetterà come sostituto di un file. Il seguente codice mostra come ciò può essere realizzato senza salvare temporaneamente il file.

@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"

La variabile csv_dicts è ora la seguente lista di dizionari:

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

Se sei nuovo su PYTHON, puoi accedere ai dati come segue:

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

Altre soluzioni implicano l'importazione del modulo io e l'uso del metodo io.Stream . Sento che questo è un approccio più diretto. Credo che il codice sia un po 'più semplice da seguire rispetto all'utilizzo del metodo io . Questo approccio è specifico dell'esempio di analisi di un file CSV caricato.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow