如何在 Flask 应用中实现带实时百分比的响应式进度条(JS + HTML)

梦磊姑娘_2288

梦磊姑娘_2288

2026-09-29

375人浏览

原创

如何在 Flask 应用中实现带实时百分比的响应式进度条(JS + HTML)

本文介绍如何在 Flask 后端配合前端 JavaScript 实现可实时更新的响应式进度条,解决长耗时任务(如文件下载、数据处理)中无法反馈进度的问题,通过 XMLHttpRequest 的 progress 事件动态更新宽度与百分比文本。

本文介绍如何在 flask 后端配合前端 javascript 实现可实时更新的响应式进度条,解决长耗时任务(如文件下载、数据处理)中无法反馈进度的问题,通过 xmlhttprequest 的 `progress` 事件动态更新宽度与百分比文本。

在 Flask Web 应用中,当后端执行耗时操作(例如批量请求远程文件、解析大体积 CSV/JSON、调用外部 API 等),默认 HTTP 请求是“黑盒式”的:前端只能等待响应完成,无法感知中间进度。而用户需要明确的视觉反馈——这正是响应式进度条的价值所在。

但需注意一个关键前提:原生 AJAX(包括 jQuery .ajax())无法直接监听服务端处理阶段的进度,它仅能捕获 HTTP 请求/响应过程中的网络传输进度(即上传/下载字节流)。因此,要使 progress 事件生效,后端必须支持 流式响应(Streaming Response) 或 分块传输(Chunked Transfer Encoding),且客户端需主动监听 xhr.upload(适用于表单上传)或 xhr(适用于下载响应体)的 progress 事件。

以下是完整、可运行的实现方案:

✅ 前端 HTML + JS(含优化样式与逻辑)



    <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>实时进度条示例</title><style>
        #progress-bar {
            width: 100%;
            max-width: 500px;
            height: 12px;
            background-color: #e0e0e0;
            border-radius: 6px;
            overflow: hidden;
            margin: 20px auto;
        }
        #progress {
            height: 100%;
            background-color: #4CAF50;
            width: 0%;
            text-align: center;
            line-height: 12px;
            color: white;
            font-size: 12px;
            transition: width 0.2s ease, background-color 0.3s;
        }
        button {
            padding: 10px 20px;
            font-size: 16px;
            background-color: #2196F3;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        button:hover { background-color: #0b7dda; }
        button:disabled { background-color: #ccc; cursor: not-allowed; }
    </style><script src="https://code.jquery.com/jquery-3.6.0.min.js"></script><div id="progress-bar">
        <div id="progress">0%</div>
    </div>
    <button id="startBtn">开始处理</button>

    <script>
        function startProcess() {
            const $btn = $('#startBtn');
            const $progress = $('#progress');

            // 禁用按钮防重复提交
            $btn.prop('disabled', true).text('处理中…');

            $.ajax({
                xhr: function() {
                    const xhr = new XMLHttpRequest();
                    // 监听响应体下载进度(关键!适用于服务端流式输出)
                    xhr.addEventListener('progress', function(evt) {
                        if (evt.lengthComputable) {
                            const percent = Math.round((evt.loaded / evt.total) * 100);
                            $progress
                                .css('width', percent + '%')
                                .text(percent + '%');
                        }
                    }, false);

                    // (可选)监听上传进度(若前端有大量数据 POST)
                    xhr.upload.addEventListener('progress', function(evt) {
                        if (evt.lengthComputable) {
                            const percent = Math.round((evt.loaded / evt.total) * 100);
                            $progress
                                .css('width', percent + '%')
                                .text('上传中 ' + percent + '%');
                        }
                    }, false);

                    return xhr;
                },
                type: 'GET', // 推荐使用 GET 避免 CSRF 复杂性(或配置 CSRF token)
                url: '/process_data',
                timeout: 300000, // 5分钟超时,避免假死
                success: function(data) {
                    alert('处理完成!共返回 ' + data.length + ' 条数据。');
                    $progress.css('width', '100%').text('完成 ✓');
                    setTimeout(() => {
                        $progress.css('background-color', '#4CAF50');
                        $btn.prop('disabled', false).text('重新开始');
                    }, 500);
                },
                error: function(xhr, status, err) {
                    let msg = '请求失败';
                    if (status === 'timeout') msg = '请求超时,请检查后端是否支持流式响应';
                    else if (xhr.status === 0) msg = '网络中断或跨域被阻止';
                    else msg += '(' + xhr.status + ')';
                    alert(msg);
                    $progress.css('width', '0%').text('错误 ×').css('background-color', '#f44336');
                    $btn.prop('disabled', false).text('重试');
                }
            });
        }

        // 绑定事件(解耦 HTML 与 JS)
        $(document).ready(function() {
            $('#startBtn').click(startProcess);
        });
    </script>

⚠️ 后端关键适配(Flask 流式响应)

原问题中 /process_data 是普通同步视图,无法触发 progress 事件。必须改为流式生成响应,并确保内容逐步写出(而非一次性 return):

html-to-pptx
html-to-pptx

将多页 HTML 演示文稿转换为美化的 PPTX 文件,便于分享和分发。

下载
from flask import Response, stream_with_context
import time
import json

@app.route('/process_data')
def process_data():
    def generate():
        # 模拟分步处理:每步发送一个 JSON 片段 + 换行符
        steps = [
            {"step": 1, "desc": "正在连接远程服务...", "progress": 20},
            {"step": 2, "desc": "下载文件中...", "progress": 50},
            {"step": 3, "desc": "解析数据...", "progress": 80},
            {"step": 4, "desc": "生成结果...", "progress": 100}
        ]

        for i, step in enumerate(steps):
            time.sleep(0.8)  # 模拟耗时操作
            yield f"data: {json.dumps(step)}\n\n"  # Server-Sent Events 格式(推荐)

        # 最终结果(可选)
        yield f"data: {json.dumps({'result': data_info_list})}\n\n"

    return Response(
        stream_with_context(generate()),
        mimetype='text/event-stream',  # 关键:启用 SSE
        headers={'Cache-Control': 'no-cache', 'X-Accel-Buffering': 'no'}
    )

? 替代方案(兼容性更强):若不使用 SSE,可改用 mimetype='text/plain' 并在前端用 xhr.responseText 解析换行分隔的 JSON,但需自行处理粘包与解析逻辑。

? 核心要点总结

  • ✅ progress 事件只对网络传输阶段有效,后端必须流式输出(如 Response(stream_with_context(...)));
  • ✅ 前端需显式设置 xhr.addEventListener('progress', ...),并用 evt.loaded / evt.total 计算百分比;
  • ✅ CSS 中为 #progress 添加 transition 实现平滑动画,width 必须设为内联样式(css('width', ...))才能被 JS 动态控制;
  • ❌ 不要依赖 $.ajax() 默认行为——它不暴露底层 XHR 的 progress 事件,必须手动构造 xhr 并返回;
  • ? 若后端无法改造为流式(如调用阻塞式第三方库),则应改用「轮询 + 后端进度存储」方案(如 Redis 记录 task_id 进度,前端定时 GET 查询)。

通过以上实现,用户将看到一个平滑增长、实时反馈的进度条,显著提升长任务场景下的体验与可信度。

前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

html js flask

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
html版权符号
html版权符号

html版权符号是“©”,可以在html源文件中直接输入或者从word中复制粘贴过来,php中文网还为大家带来html的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.14

5215

7

html在线编辑器
html在线编辑器

html在线编辑器是用于在线编辑的工具,编辑的内容是基于HTML的文档。它经常被应用于留言板留言、论坛发贴、Blog编写日志或等需要用户输入普通HTML的地方,是Web应用的常用模块之一。php中文网为大家带来了html在线编辑器的相关教程、以及相关文章等内容,供大家免费下载使用。

2023.06.21

3012

4

html网页制作
html网页制作

html网页制作是指使用超文本标记语言来设计和创建网页的过程,html是一种标记语言,它使用标记来描述文档结构和语义,并定义了网页中的各种元素和内容的呈现方式。本专题为大家提供html网页制作的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.31

2670

5

html空格
html空格

html空格是一种用于在网页中添加间隔和对齐文本的特殊字符,被用于在网页中插入额外的空间,以改变元素之间的排列和对齐方式。本专题为大家提供html空格的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.01

2699

5

html是什么
html是什么

HTML是一种标准标记语言,用于创建和呈现网页的结构和内容,是互联网发展的基石,为网页开发提供了丰富的功能和灵活性。本专题为大家提供html相关的各种文章、以及下载和课程。

2023.08.11

4619

6

html字体大小怎么设置
html字体大小怎么设置

在网页设计中,字体大小的选择是至关重要的。合理的字体大小不仅可以提升网页的可读性,还能够影响用户对网页整体布局的感知。php中文网将介绍一些常用的方法和技巧,帮助您在HTML中设置合适的字体大小。

2023.08.11

2661

3

html转txt
html转txt

html转txt的方法有使用文本编辑器、使用在线转换工具和使用Python编程。本专题为大家提供html转txt相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.31

2449

3

html文本框代码怎么写
html文本框代码怎么写

html文本框代码:1、单行文本框【<input type="text" style="height:..;width:..;" />】;2、多行文本框【textarea style=";height:;"></textare】。

2023.09.01

2228

6

HTML嵌入CSS样式的方法
HTML嵌入CSS样式的方法

HTML嵌入CSS样式的方法有内联样式、内部样式表和外部样式表。本专题为大家提供CSS样式相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.20

2208

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
GDB 17.2 官方文档集合
GDB 17.2 官方文档集合

共0课时 | 0人学习

Bootstrap 入门安装配置
Bootstrap 入门安装配置

共0课时 | 0人学习

38+ PhpStorm 提示和技巧
38+ PhpStorm 提示和技巧

共1课时 | 214人学习