使用 Flask 处理 XMLHttpRequest:最好的方法

问题描述 投票:0回答:1
我编写了一个简单的网络服务器,用于获取照片并将其存储在服务器中。 我不是 javascript 专家,我正在寻找一些技巧来帮助我找到管理 js 和 Flask 之间数据的好方法。

这是我的 index.html 文件,我在其中创建一个小表单,在其中插入照片和一个运行小 js 函数的按钮:

<!DOCTYPE html> <html> <head> <title>Take or select photo(s) and upload</title> <script type="text/javascript"> function fileSelected() { var count = document.getElementById('fileToUpload').files.length; document.getElementById('details').innerHTML = ""; for (var index = 0; index < count; index ++) { var file = document.getElementById('fileToUpload').files[index]; var fileSize = 0; if (file.size > 1024 * 1024) fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB'; else fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB'; document.getElementById('details').innerHTML += 'Name: ' + file.name + '<br>Size: ' + fileSize + '<br>Type: ' + file.type; document.getElementById('details').innerHTML += '<p>'; } } function uploadFile() { var fd = new FormData(); var count = document.getElementById('fileToUpload').files.length; for (var index = 0; index < count; index ++) { var file = document.getElementById('fileToUpload').files[index]; //console.log(file) fd.append(file.name, file); } var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", uploadProgress, false); xhr.addEventListener("load", uploadComplete, false); xhr.addEventListener("error", uploadFailed, false); xhr.addEventListener("abort", uploadCanceled, false); xhr.open("POST", "/save", true); xhr.send(fd); console.log(fd) } function uploadProgress(evt) { if (evt.lengthComputable) { var percentComplete = Math.round(evt.loaded * 100 / evt.total); document.getElementById('progress').innerHTML = percentComplete.toString() + '%'; } else { document.getElementById('progress').innerHTML = 'unable to compute'; } } function uploadComplete(evt) { /* This event is raised when the server send back a response */ alert(evt.target.responseText); } function uploadFailed(evt) { alert("There was an error attempting to upload the file."); } function uploadCanceled(evt) { alert("The upload has been canceled by the user or the browser dropped the connection."); } </script> </head> <body> <form id="form1" enctype="multipart/form-data" method="post" > <div> <label for="fileToUpload">Take or select photo(s)</label><br /> <input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();" accept="image/*" capture="camera" /> </div> <div id="details"></div> <div class="input-group"> <input type="button" onclick="uploadFile()" value="Upload" /> </div> <div id="progress"></div> </form> <br><br> <h3>{{message}}</h3> </body> </html>
这是我的 main.py:

from flask import Flask, render_template, Response, request,redirect, flash import base64 from flask_bootstrap import Bootstrap5 import json #instatiate flask app app = Flask(__name__, template_folder='./templates') bootstrap = Bootstrap5(app) @app.route('/', methods = ['GET', 'POST']) def index(): print(request.method) status = "" if request.method == 'GET': return render_template('./index.html', message=status) else: try: #photo = request.files['fileToUpload'] for key in request.files.keys: print(request.files.get(key)) #photo.save("upload/myfile.jpg") #status='Uploaded' #flash("Updated") except: status = "Something went wrong" return render_template("./index.html", message=status) @app.route('/save', methods = ['POST']) def save(): try: files = request.files.lists() for photo in files: photo[1][0].save("upload/{0}".format(photo[0])) return redirect("/") except: return render_template("./index.html", message="FAILED") if __name__ == '__main__': app.run(host="0.0.0.0")
我的问题是:有更好的方法吗?也许使用 json 或将文件转换为字典而不是列表?
可以支持多用户同时使用吗?
我可以在烧瓶端使用异步函数处理请求吗?
谢谢大家!

javascript python flask xmlhttprequest
1个回答
1
投票
你的 Flask 应用程序可以简化很多:

from flask import Flask, render_template, request from flask_bootstrap import Bootstrap5 from werkzeug.utils import secure_filename import os # instatiate flask app app = Flask(__name__, template_folder='./templates') bootstrap = Bootstrap5(app) @app.route('/', methods=['GET']) def index(): return render_template("index.html") @app.route('/save', methods=['POST']) def save(): files = request.files.values() for photo in files: filename = secure_filename(photo.filename) photo.save(os.path.join('upload', filename)) return 'Upload successful' if __name__ == '__main__': app.run(host="0.0.0.0")
由于您仅 POST 到 

/save

,因此您不需要在 
index
 中进行任何 POST 逻辑。为了安全起见,我已将 
save
 路线更改为使用 
secure_filename
。您不需要在 
save
 中尝试/例外,因为如果失败,您的 
uploadFailed
 JavaScript 将被调用。

您的 JavaScript 看起来不错,但您需要将

multiple

 属性添加到文件输入以接受多个文件:

<input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();" accept="image/*" capture="camera" multiple/>
如果您想支持多个用户,请查看

Flask-Login或这个教程

© www.soinside.com 2019 - 2024. All rights reserved.