Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
python:flask:upload [2020/12/05 08:18] marclebrun [Vue] |
python:flask:upload [2021/10/08 07:39] (Version actuelle) marclebrun [Javascript] |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
====== Upload ====== | ====== Upload ====== | ||
- | ===== Template formulaire ===== | + | Tutoriel: [[https://pythonise.com/series/learning-flask/flask-uploading-files]] |
- | //Cet exemple utilise **Bootstrap** pour styler le formulaire.// | + | ===== 1. Upload traditionnel ===== |
- | <code html upload.html> | + | ==== Template formulaire ==== |
- | <div class="container"> | + | |
- | <div class="row"> | + | |
- | <div class="col"> | + | |
- | <h1>Uploader un fichier</h1> | + | <code html upload.html> |
+ | <h1>Uploader un fichier</h1> | ||
- | <form method="POST" enctype="multipart/form-data"> | + | <form method="POST" enctype="multipart/form-data"> |
- | + | <input type="file" name="fichier" id="fichier"> | |
- | <div class="form-group"> | + | <label for="fichier">Sélectionnez un fichier...</label> |
- | <div class="custom-file"> | + | <button type="submit">Envoyer</button> |
- | <input type="file" | + | </form> |
- | class="custom-file-input" | + | |
- | name="fichier" id="fichier"> | + | |
- | <label for="fichier" | + | |
- | class="custom-file-label">Sélectionnez un fichier...</label> | + | |
- | </div> | + | |
- | + | ||
- | <button type="submit" class="btn btn-primary mt-3">Uploader</button> | + | |
- | + | ||
- | </div> | + | |
- | + | ||
- | </form> | + | |
- | + | ||
- | </div> | + | |
- | </div> | + | |
- | </div> | + | |
</code> | </code> | ||
- | ===== Vue ===== | + | ==== Vue ==== |
<code python app.py> | <code python app.py> | ||
@app.route("/test_upload", methods=["GET", "POST"]) | @app.route("/test_upload", methods=["GET", "POST"]) | ||
def test_upload(): | def test_upload(): | ||
+ | |||
+ | # Si le formulaire a été posté | ||
if request.method == "POST": | if request.method == "POST": | ||
if request.files: | if request.files: | ||
fichier = request.files["fichier"] | fichier = request.files["fichier"] | ||
| | ||
- | ... (faire quelque chose avec le fichier) ... | + | # ... faire quelque chose avec le fichier ... |
| | ||
return redirect(request.url) | return redirect(request.url) | ||
| | ||
- | return render_template("admin/test_upload.html") | + | # Sinon afficher le formulaire |
+ | return render_template("upload.html") | ||
+ | </code> | ||
+ | |||
+ | ==== Utilisation du fichier ==== | ||
+ | |||
+ | Pour utiliser le fichier uploadé il faut l'enregistrer quelque part. | ||
+ | |||
+ | Définir une valeur dans la configuration. Le chemin doit être absolu. Il peut | ||
+ | être en dehors de l'application. | ||
+ | |||
+ | Par exemple : | ||
+ | |||
+ | <code python> | ||
+ | app.config['UPLOAD_PATH'] = "/home/marc/website/uploads" | ||
+ | </code> | ||
+ | |||
+ | Ensuite : | ||
+ | |||
+ | <code python> | ||
+ | import os | ||
+ | from werkzeug.utils import secure_filename | ||
+ | |||
+ | filename = secure_filename(fichier.filename) | ||
+ | |||
+ | fichier.save(os.path.join(app.config["UPLOAD_PATH"], filename)) | ||
+ | </code> | ||
+ | |||
+ | ^ fichier.filename | Nom original du fichier uploadé | | ||
+ | ^ fichier.save(path) | Enregistre le fichier | | ||
+ | ^ secure_filename | "nettoyage" du nom du fichier | | ||
+ | |||
+ | ==== Sécurité ==== | ||
+ | |||
+ | Vérifier qu'il y a bien eu un fichier sélectionné : | ||
+ | |||
+ | <code python> | ||
+ | fichier = request.files["fichier"] | ||
+ | if fichier.filename: | ||
+ | ... | ||
+ | else: | ||
+ | flash(u"Veuillez sélectionner un fichier !", "danger") | ||
+ | return redirect(request.url) | ||
+ | </code> | ||
+ | |||
+ | Vérifier que le type fichier est autorisé : | ||
+ | |||
+ | <code python> | ||
+ | ext = filename.rsplit(".", 1)[1] | ||
+ | if ext.upper() in ["JPEG", "JPG", "PNG", "GIF"]: | ||
+ | ... | ||
+ | else: | ||
+ | flash(u"Ce type de fichier n'est pas autorisé !", "danger") | ||
+ | return redirect(request.url) | ||
+ | </code> | ||
+ | |||
+ | ===== 2. Upload via Ajax ===== | ||
+ | |||
+ | ==== Formulaire ==== | ||
+ | |||
+ | <code html upload.html> | ||
+ | <h1>Ajax File Upload</h1> | ||
+ | |||
+ | <form id="frmUpload" method="POST" enctype="multipart/form-data"> | ||
+ | <label for="edtFile">Sélectionnez un fichier à uploader</label><br/> | ||
+ | <input type="file" name="edtFile" id="edtFile"><br/> | ||
+ | <button id="btnUpload">Envoyer</button> | ||
+ | </form> | ||
+ | </code> | ||
+ | |||
+ | ==== Javascript ==== | ||
+ | |||
+ | <code javascript upload.js> | ||
+ | let frmUpload = document.getElementById('frmUpload'); | ||
+ | let btnUpload = document.getElementById('btnUpload'); | ||
+ | |||
+ | btnUpload.addEventListener('click', event => { btnUploadClick(event) }); | ||
+ | |||
+ | function btnUploadClick(event) { | ||
+ | |||
+ | event.preventDefault(); | ||
+ | |||
+ | fetch('/upload', { | ||
+ | method: 'POST', | ||
+ | body : new FormData(frmUpload) | ||
+ | }).then( | ||
+ | //... | ||
+ | ) | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== Vue ==== | ||
+ | |||
+ | <code python app.py> | ||
+ | @app.route("/upload", methods=["POST"]) | ||
+ | def upload(): | ||
+ | result = {} | ||
+ | |||
+ | if 'edtFile' in request.files: | ||
+ | if request.files['edtFile'].filename: | ||
+ | |||
+ | fichier = request.files['edtFile'] | ||
+ | fichier.save('/home/marc/...') | ||
+ | |||
+ | # ... | ||
+ | |||
+ | else: | ||
+ | |||
+ | result['error'] = "Erreur, il n'y a pas de fichier." | ||
+ | |||
+ | return jsonify(result) | ||
</code> | </code> | ||