Flask
Téléchargement de fichier
Recherche…
Syntaxe
- request.files ['name'] # fichier unique requis
- request.files.get ('name') # Aucun s'il n'est pas posté
- request.files.getlist ('name') # liste de zéro ou plusieurs fichiers publiés
- CombinedMultiDict ((request.files, request.form)) # combine les données de formulaire et de fichier
Téléchargement de fichiers
Formulaire HTML
- Utilisez une entrée de type de
file
et le navigateur fournira un champ permettant à l'utilisateur de sélectionner un fichier à télécharger. - Seuls les formulaires avec la méthode
post
peuvent envoyer des données de fichier. - Assurez-vous de définir l'
enctype=multipart/form-data
. Sinon, le nom du fichier sera envoyé mais pas les données du fichier. - Utilisez l'attribut
multiple
sur l'entrée pour permettre de sélectionner plusieurs fichiers pour le champ unique.
<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>
Demandes Python
Requests est une bibliothèque Python puissante pour faire des requêtes HTTP. Vous pouvez l'utiliser (ou d'autres outils) pour publier des fichiers sans navigateur.
- Ouvrez les fichiers à lire en mode binaire.
- Il existe plusieurs structures de données que les
files
prennent. Cela montre une liste de tuples(name, data)
, qui autorise plusieurs fichiers comme le formulaire ci-dessus.
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)
Ceci n'est pas censé être une liste exhaustive. Pour des exemples d'utilisation de votre outil préféré ou de scénarios plus complexes, consultez la documentation de cet outil.
Enregistrer les téléchargements sur le serveur
Les fichiers téléchargés sont disponibles dans request.files
, un MultiDict
champ de mappage MultiDict
pour les objets de fichier. Utilisez getlist
- au lieu de []
ou get
- si plusieurs fichiers ont été téléchargés avec le même nom de champ.
request.files['profile'] # single file (even if multiple were sent)
request.files.getlist('charts') # list of files (even if one was sent)
Les objets dans request.files
ont une méthode de save
qui enregistre le fichier localement. Créez un répertoire commun pour enregistrer les fichiers.
L'attribut filename
est le nom avec lequel le fichier a été téléchargé. Cela peut être défini de manière arbitraire par le client, alors transmettez-le via la méthode secure_filename
pour générer un nom valide et sûr sous secure_filename
enregistrer. Cela ne garantit pas que le nom est unique , de sorte que les fichiers existants seront écrasés à moins que vous ne fassiez un travail supplémentaire pour le détecter.
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')
Transmission de données à WTForms et Flask-WTF
WTForms fournit un FileField
pour restituer une entrée de type de fichier. Il ne fait rien de spécial avec les données téléchargées. Toutefois, comme Flask divise les données de formulaire ( request.form
) et les données de fichier ( request.files
), vous devez vous assurer de transmettre les données correctes lors de la création du formulaire. Vous pouvez utiliser un CombinedMultiDict
pour combiner les deux en une structure unique que WTForms comprend.
form = ProfileForm(CombinedMultiDict((request.files, request.form)))
Si vous utilisez Flask-WTF , une extension pour intégrer Flask et WTForms, le transfert des données correctes sera géré automatiquement pour vous.
En raison d'un bogue dans WTForms, un seul fichier sera présent pour chaque champ, même si plusieurs ont été téléchargés. Voir ce numéro pour plus de détails. Il sera corrigé dans 3.0.
TÉLÉCHARGER LE FICHIER PARSE CSV EN TANT QUE LISTE DE DICTIONNAIRES EN FLACON SANS ÉCONOMIE
Les développeurs doivent souvent concevoir des sites Web permettant aux utilisateurs de télécharger un fichier CSV. En règle générale, il n’ya aucune raison de sauvegarder le fichier CSV actuel car les données seront traitées et / ou stockées dans une base de données une fois téléchargées. Cependant, la plupart des méthodes d'analyse syntaxique des données CSV, si ce n'est la plupart, nécessitent que les données soient lues sous forme de fichier. Cela peut poser un problème si vous utilisez FLASK pour le développement Web.
Supposons que notre CSV a une ligne d'en-tête et ressemble à ceci:
h1,h2,h3
'yellow','orange','blue'
'green','white','black'
'orange','pink','purple'
Maintenant, supposons que le formulaire HTML pour télécharger un fichier est comme suit:
<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>
Puisque personne ne veut réinventer la roue, vous décidez d' importer csv dans votre script FLASK . Il n'y a aucune garantie que les utilisateurs téléchargent le fichier csv avec les colonnes dans le bon ordre. Si le fichier csv a une ligne d'en-tête, alors, à l'aide de la méthode csv.DictReader , vous pouvez lire le fichier CSV sous la forme d'une liste de dictionnaires, en saisissant les entrées de la ligne d'en-tête. Cependant, csv.DictReader a besoin d'un fichier et n'accepte pas directement les chaînes. Vous pensez peut-être que vous devez utiliser les méthodes FLASK pour enregistrer d'abord le fichier téléchargé, obtenir le nouveau nom et l'emplacement du fichier, l'ouvrir à l'aide de csv.DictReader , puis supprimer le fichier. Semble un peu comme un déchet.
Heureusement, nous pouvons obtenir le contenu du fichier sous forme de chaîne, puis diviser la chaîne par des lignes terminées. La méthode csv csv.DictReader acceptera ceci comme substitut à un fichier. Le code suivant montre comment cela peut être accompli sans enregistrer temporairement le fichier.
@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 variable csv_dicts est maintenant la liste de dictionnaires suivante:
csv_dicts =
[
{'h1':'yellow','h2':'orange','h3':'blue'},
{'h1':'green','h2':'white','h3':'black'},
{'h1':'orange','h2':'pink','h3':'purple'}
]
Si vous êtes nouveau sur PYTHON, vous pouvez accéder aux données suivantes:
csv_dicts[1]['h2'] = 'white'
csv_dicts[0]['h3'] = 'blue'
D'autres solutions impliquent l'importation du module io et utilisent la méthode io.Stream . Je pense que c'est une approche plus simple. Je crois que le code est un peu plus facile à suivre que d'utiliser la méthode io . Cette approche est spécifique à l'exemple d'analyse d'un fichier CSV téléchargé.