在Python Flask中实现带百分比的响应式进度条,无法获取处理进度
Flask + JS 实现后台处理进度条解决方案
问题分析
你当前的代码无法获取后台处理进度的核心原因:
- XHR的
progress事件仅监听HTTP请求的传输进度(上传/下载字节的进度),但后台的耗时处理是在服务器端执行的,此时HTTP响应还未开始返回,前端无法捕获中间进度。 - Flask默认是完成所有业务逻辑后才返回完整响应,不会实时推送处理进度。
解决方案:使用定时轮询+后台线程实现实时进度推送
通过后台线程执行耗时任务,同时提供进度查询接口,前端定时获取进度并更新UI,是实现这类需求的简单可靠方案。
1. 修正后端Flask代码
from flask import Flask, render_template, jsonify, session import time import threading import uuid app = Flask(__name__) app.secret_key = 'your-secure-secret-key' # 生产环境请使用安全密钥 # 模拟耗时处理任务,实时更新进度 def long_running_task(task_id): # 替换为你的实际处理逻辑:请求外部接口、读取处理数据等 total_steps = 10 for step in range(total_steps): time.sleep(1) # 更新进度到session(生产环境建议用Redis等分布式存储,避免多线程冲突) session[f'progress_{task_id}'] = (step + 1) * 10 session.permanent = True @app.route('/test') def testindex(): return render_template('layouts/loading.html') @app.route('/start_process') def start_process(): # 生成唯一任务ID,避免多用户进度冲突 task_id = str(uuid.uuid4()) # 启动线程执行耗时任务,不阻塞Flask主线程 threading.Thread(target=long_running_task, args=(task_id,)).start() return jsonify({'task_id': task_id}) @app.route('/get_progress/<task_id>') def get_progress(task_id): # 返回当前任务进度,默认0 progress = session.get(f'progress_{task_id}', 0) return jsonify({'progress': progress})
2. 修正前端HTML/JS代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Loading Progress Bar</title> <style> #progress-bar { width: 100%; background-color: #f3f3f3; } #progress { width: 0%; height: 30px; background-color: #4caf50; text-align: center; line-height: 30px; color: white; transition: width 0.3s ease; } </style> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> </head> <body> <div id="progress-bar"> <div id="progress">0%</div> </div> <br> <button onclick="startProcess()">Start Process</button> <script> function startProcess() { const progressBar = document.getElementById('progress'); // 重置进度条状态 progressBar.style.width = '0%'; progressBar.textContent = '0%'; // 启动后台任务 $.get('/start_process', function(res) { const taskId = res.task_id; // 定时轮询获取进度 const pollInterval = setInterval(() => { $.get(`/get_progress/${taskId}`, function(progressRes) { const currentProgress = progressRes.progress; // 更新UI progressBar.style.width = `${currentProgress}%`; progressBar.textContent = `${currentProgress}%`; // 进度完成后停止轮询 if (currentProgress >= 100) { clearInterval(pollInterval); alert('处理完成!'); } }); }, 500); // 每500ms查询一次,可根据需求调整 }); } </script> </body> </html>
关键注意事项
- 后端必须用线程执行耗时任务,否则Flask主线程会被阻塞,无法响应后续的进度查询请求。
- 进度存储:示例用Flask Session,生产环境建议用Redis等分布式存储,避免多进程/多线程环境下的进度共享问题。
- 前端轮询间隔:根据处理任务的耗时调整,间隔太小会增加服务器压力,太大则进度更新不及时。
内容的提问来源于stack exchange,提问作者Vismaya Hostcurator
相关产品推荐
相关产品推荐

