Flask
Upload di file
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.