You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask后端返回send_file时,如何向前端发送任务进度数据?

实现Flask下载进度实时更新的简单方案

你原来的代码是一次性返回压缩包,没法中途给前端发消息,得改成「后台干活+前端定期查进度」的模式,下面是具体步骤:

一、后端代码修改

1. 导入必要模块

先把需要的工具包导入进来:

from flask import Flask, request, redirect, url_for, render_template, session, jsonify, send_file
from zipfile import ZipFile
import threading
import os
from pytube import YouTube

2. 改写接口逻辑

把下载打包的任务放到后台线程,同时新增一个接口让前端查进度:

@app.route('/main', methods=['GET', 'POST'])
def main():
    if request.method == 'POST':
        if not current_user:
            return redirect(url_for('home'))
        # 初始化进度:当前完成数、总文件数、是否完成
        session['download_progress'] = {'current': 0, 'total': 10, 'done': False}
        # 启动后台线程处理下载打包
        thread = threading.Thread(target=process_files, args=(current_user.id,))
        thread.daemon = True  # 后台线程随主服务关闭自动结束
        thread.start()
        # 跳转到进度展示页
        return render_template('progress.html', user=current_user)
    return render_template('main.html', user=current_user)

# 后台处理下载打包的函数
def process_files(user_id):
    zip_temp_path = f'temp_{user_id}.zip'
    total_files = 10  # 你需要提前确定总共有多少个要下载的文件
    session['download_progress']['total'] = total_files
    
    with ZipFile(zip_temp_path, "w") as zip_file:
        for counter in range(1, total_files+1):
            # 这里写你的pytube下载逻辑
            # 示例:yt = YouTube("目标视频链接"); stream = yt.streams.get_highest_resolution(); stream.download()
            # 把下载好的文件加入压缩包:zip_file.write(下载的文件名)
            
            # 更新当前进度到会话
            session['download_progress']['current'] = counter
    
    # 标记任务完成
    session['download_progress']['done'] = True

# 前端用来查询进度的接口
@app.route('/get-progress')
def get_progress():
    progress = session.get('download_progress', {'current': 0, 'total': 0, 'done': False})
    return jsonify(progress)

# 提供压缩包下载的接口
@app.route('/download-zip')
def download_zip():
    if not current_user:
        return redirect(url_for('home'))
    zip_temp_path = f'temp_{current_user.id}.zip'
    if os.path.exists(zip_temp_path):
        response = send_file(zip_temp_path, download_name="something.zip", as_attachment=True)
        # 下载完成后删除临时文件
        os.remove(zip_temp_path)
        # 清空会话里的进度数据
        session.pop('download_progress', None)
        return response
    return "文件尚未准备好,请稍后重试"

二、前端页面修改

1. 进度展示页(progress.html)

这个页面负责显示实时进度,完成后自动触发下载:

<!DOCTYPE html>
<html>
<head>
    <title>处理中...</title>
</head>
<body>
    <h3>正在为您打包文件</h3>
    <div id="progress-info">0/0个文件已完成</div>

    <script>
        // 每隔1秒查询一次进度
        const progressChecker = setInterval(() => {
            fetch('/get-progress')
                .then(res => res.json())
                .then(data => {
                    // 更新页面上的进度文本
                    document.getElementById('progress-info').textContent = 
                        `${data.current}/${data.total}个文件已完成`;
                    
                    // 如果任务完成,停止查询并跳转下载
                    if (data.done) {
                        clearInterval(progressChecker);
                        window.location.href = '/download-zip';
                    }
                });
        }, 1000);
    </script>
</body>
</html>

2. 主页面(main.html)

保持原有提交按钮即可,点击后会触发后台任务并跳转到进度页。

三、核心逻辑说明

  1. 后台线程:把下载打包的耗时操作放到后台,避免前端页面长时间卡住。
  2. 会话存进度:每个用户的进度存在自己的会话中,不会和其他用户的任务混淆。
  3. 前端轮询:用fetch定期请求进度接口,拿到数据后更新页面,任务完成后自动触发下载。
  4. 临时文件处理:压缩包临时存在服务器,下载完成后立即删除,避免占用存储空间。

内容的提问来源于stack exchange,提问作者MyPing0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 07:05:22