如何将Javascript上传的附件发送至Python/Flask后端?集成问题求助
文件上传集成问题:前端无法将文件发送到Flask后端
我编写了文件上传代码,但无法实现JavaScript与Flask的集成。目前前端已成功接收文件,但无法将其发送至后端。以下是我的代码,也尝试过一些方案但问题仍未解决,请求帮助。
JavaScript代码
//DOM const $ = document.querySelector.bind(document); //APP let App = {}; App.init = (function () { //Init function handleFileSelect(evt) { const files = evt.target.files; // FileList object //files template let template = `${Object.keys(files) .map(file => `<div class="file file--${file}"> <div class="name"><span>${files[file].name}</span></div> <div class="progress active"></div> <div class="done"> <a href="" target="_blank"> </a> </div> </div> </div>`) .join("")}`; $("#drop").classList.add("hidden"); $("footer").classList.add("hasFiles"); $(".importar").classList.add("active"); $(".submit").classList.add("active"); setTimeout(() => { $(".list-files").innerHTML = template; }, 1000); Object.keys(files).forEach(file => { let load = 2000 + (file * 2000); // fake load setTimeout(() => { $(`.file--${file}`).querySelector(".progress").classList.remove("active"); $(`.file--${file}`).querySelector(".done").classList.add("anim"); }, load); }); } // trigger input $("#triggerFile").addEventListener("click", evt => { evt.preventDefault(); $("input[type=file]").click(); }); $("#triggerFile2").addEventListener("click", evt => { evt.preventDefault(); $("input[type=file]").click(); }); // drop events $("#drop").ondragleave = evt => { $("#drop").classList.remove("active"); evt.preventDefault(); }; $(`#drop`).ondragover = $("#drop").ondragenter = evt => { $("#drop").classList.add("active"); evt.preventDefault(); }; $("#drop").ondrop = evt => { $("input[type=file]").files = evt.dataTransfer.files; $("footer").classList.add("hasFiles"); $("#drop").classList.remove("active"); evt.preventDefault(); }; //upload more $(".importar").addEventListener("click", () => { $(".list-files").innerHTML = ""; $("footer").classList.remove("hasFiles"); $(".importar").classList.remove("active"); $(".submit").classList.remove("active"); setTimeout(() => { $("#drop").classList.remove("hidden"); }, 500); }); // input change $("input[type=file]").addEventListener("change", handleFileSelect); })();
HTML代码
<form method="post" action="/" enctype="multipart/form-data" id="myForm"> <header> <p> <span class="up">up</span> <span class="load">load</span> </p> </header> <div class="body" id="drop"> <i class="fa fa-cloud-upload" aria-hidden="true" id="triggerFile"></i> <p id="text-upload" class="pointer-none"><a href="" id="triggerFile2"> <strong>Browse</strong></a> to begin the upload </p> <input type="file" multiple="multiple" /> </div> <footer> <div class="divider"> <span> <AR>FILES</AR> </span> </div> <div class="list-files"> <!-- template --> </div> <button class="importar">Clear</button> <button class="submit" type="submit" value="Submit""">Submit</button> </footer> </form>
Flask/Python代码
import os from flask import Flask, flash, request, redirect, render_template from werkzeug.utils import secure_filename app=Flask(__name__) app.secret_key = "secret key" app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 path = os.getcwd() # file Upload UPLOAD_FOLDER = os.path.join(path, 'uploads') if not os.path.isdir(UPLOAD_FOLDER): os.mkdir(UPLOAD_FOLDER) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER ALLOWED_EXTENSIONS = set(['xlsx', 'xls']) def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @app.route('/') def upload_form(): return render_template('index.html') @app.route('/', methods=['POST']) def upload_file(): if request.method == 'POST': # check if the post request has the file part if 'file' not in request.files: flash('No file part') return redirect(request.url) file = request.files['file'] if file.filename == '': flash('No file selected for uploading') return redirect(request.url) if file and allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) flash('File successfully uploaded') return redirect('/') else: flash('Allowed file types are txt, pdf, png, jpg, jpeg, gif') return redirect(request.url) if __name__ == "__main__": app.run(host = '127.0.0.1',port = 5000, debug = False)
已尝试的方案
- 基于Ajax的JavaScript文件上传示例
- JavaScript与Python文件传输方案
- Flask API文件上传下载指南
问题核心原因及修复方案
1. 文件输入框缺少name属性
Flask后端通过request.files['file']获取上传文件,必须匹配前端文件输入框的name属性。当前HTML中的文件输入框未设置该属性,导致后端无法识别文件字段。
修复:
修改HTML中的文件输入框:
<input type="file" name="file" multiple="multiple" />
2. 提交按钮语法错误
提交按钮的value属性多了一个引号(value="Submit""),会导致HTML解析异常,阻碍表单正常提交。
修复:
修正按钮代码:
<button class="submit" type="submit" value="Submit">Submit</button>
3. 拖拽上传的兼容性问题
直接给input.files赋值evt.dataTransfer.files在部分浏览器中会因安全限制失效,需通过DataTransfer重构并手动触发change事件同步UI。
修复JS拖拽事件:
$("#drop").ondrop = evt => { evt.preventDefault(); const dt = new DataTransfer(); [...evt.dataTransfer.files].forEach(file => dt.items.add(file)); $("input[type=file]").files = dt.files; // 手动触发change事件更新UI $("input[type=file]").dispatchEvent(new Event('change')); $("#drop").classList.remove("active"); $("footer").classList.add("hasFiles"); };
4. 模板需渲染Flash消息
后端flash()返回的提示信息需要在模板中渲染才能显示,否则无法得知提交结果。在index.html中添加:
{% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %} <div style="color: red; margin: 10px 0;">{{ message }}</div> {% endfor %} {% endif %} {% endwith %}
5. 多文件上传的后端适配(可选)
若需支持多文件上传,后端需遍历request.files.getlist('file')而非仅获取单个文件:
修复Flask后端:
@app.route('/', methods=['POST']) def upload_file(): if request.method == 'POST': if 'file' not in request.files: flash('没有文件部分') return redirect(request.url) files = request.files.getlist('file') for file in files: if file.filename == '': flash('未选择文件') return redirect(request.url) if file and allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) flash('所有文件上传成功') return redirect('/') flash('请求方法错误') return redirect(request.url)
内容的提问来源于stack exchange,提问作者Roberto
相关产品推荐
相关产品推荐

