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

Flask表单提交后,如何用JQuery实现文件下载完成后刷新页面?

问题描述

我有一个通过POST方法向Flask应用上传文件的页面,了解到Flask的路由无法同时处理send_file和redirect操作,所以目前的替代方案是在POST请求成功后刷新页面。

现有HTML代码

{% extends "base.html" %}
{% block head %}
<!-- {# <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/leaf.css') }}"> #} -->
<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
<!-- <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/base.css') }}"> -->
{% endblock %}
{% block content %}
<div id="vo_budget_file_settings">
    {# <a href="/generatecleanbudgetfile" class="btn btn-primary">Upload Final CRO Budget File</a> #}
    <p>Please upload the final CRO budget File</p>
    <form class="" action="/generatecleanbudgetfile" method=POST enctype=multipart/form-data>
        <input type="file" name="data_file" accept=".xls, .xlsx, .xlsm"/>
        <input type="submit" value="Begin Format" onclick="loading();"/>
    </form>
</div>
<!-- funtion to show css spinner on button click -->
<script type="text/javascript">
    function loading(){
      $(".loader").show();     
    }
    </script>
<script type="text/javascript">
    // Reload page 60 seconds after form submission
    $("vo_budget_file_settings").onsubmit = setTimeout(function () {
        window.location = "/bugetformatter"; 
        }, 60000);
        console.log(window.location);
    </script>
{% endblock %}

现有Flask应用代码

@app.route('/bugetformatter')
def data_request_portal():
    return render_template('CROBudgetFormatter.html', title='CRO Budget Formatting Tool')

@app.route('/generatecleanbudgetfile', methods=['GET', 'POST'])
def clean_budget():
    file = request.files.get('data_file')
    app.logger.info('Conversion has started')
    try:
        if request.method == 'POST':
            file = request.files.get('data_file')
            file.seek(0)
            buffer = budget_cleaner(file)
            buffer.seek(0)
            app.logger.info('Conversion Complete')
            return send_file(
            buffer,
            as_attachment=True,
            attachment_filename=f'stripped_budget_{dt.today().strftime("%m.%d.%Y")}.xlsx',
            mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            )
    except:
        return render_template('error_type.html', title='Unable to process uploaded budget.')

核心疑问

有没有类似回调的脚本,能在请求完成且文件下载到浏览器后再重新加载页面?现在用60秒定时器刷新,但担心任务耗时超过60秒,想把刷新和文件下载绑定。


解决方案

可以通过AJAX异步上传文件,在后端返回文件数据后手动触发下载,完成后再执行页面刷新,精准控制刷新时机,摆脱定时器依赖。

步骤1:修改HTML表单与前端脚本

将原生表单提交改为AJAX提交,保留加载状态提示:

{% extends "base.html" %}
{% block head %}
<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
{% endblock %}
{% block content %}
<div id="vo_budget_file_settings">
    <p>Please upload the final CRO budget File</p>
    <form id="upload-form" enctype=multipart/form-data>
        <input type="file" name="data_file" accept=".xls, .xlsx, .xlsm"/>
        <input type="button" value="Begin Format" onclick="handleUpload();"/>
    </form>
</div>
<script type="text/javascript">
    function loading(){
      $(".loader").show();     
    }

    function handleUpload() {
        loading();
        const formData = new FormData(document.getElementById('upload-form'));
        
        $.ajax({
            url: '/generatecleanbudgetfile',
            type: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            xhrFields: {
                responseType: 'blob' // 以二进制blob格式接收文件
            },
            success: function(blob, status, xhr) {
                // 从响应头提取文件名
                const contentDisposition = xhr.getResponseHeader('Content-Disposition');
                let filename = 'stripped_budget.xlsx';
                if (contentDisposition) {
                    const matches = contentDisposition.match(/filename="?([^"]+)"?/);
                    if (matches && matches[1]) {
                        filename = matches[1];
                    }
                }

                // 创建临时链接触发浏览器下载
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = filename;
                document.body.appendChild(a);
                a.click();
                window.URL.revokeObjectURL(url);
                document.body.removeChild(a);

                // 下载完成后立即刷新页面
                window.location.href = "/bugetformatter";
            },
            error: function() {
                // 错误时跳转到错误页面
                window.location.href = "/error_type";
            },
            complete: function() {
                // 可选:隐藏加载状态
                $(".loader").hide();
            }
        });
    }
</script>
{% endblock %}

步骤2:调整Flask路由(优化原有逻辑)

原send_file逻辑无需大幅修改,补充错误状态码返回,让AJAX能正确识别错误:

from flask import request, send_file, render_template
import datetime as dt

@app.route('/bugetformatter')
def data_request_portal():
    return render_template('CROBudgetFormatter.html', title='CRO Budget Formatting Tool')

@app.route('/generatecleanbudgetfile', methods=['POST'])
def clean_budget():
    app.logger.info('Conversion has started')
    try:
        file = request.files.get('data_file')
        if not file:
            raise ValueError("No file uploaded")
        
        file.seek(0)
        buffer = budget_cleaner(file)
        buffer.seek(0)
        app.logger.info('Conversion Complete')
        
        filename = f'stripped_budget_{dt.today().strftime("%m.%d.%Y")}.xlsx'
        return send_file(
            buffer,
            as_attachment=True,
            attachment_filename=filename,
            mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        )
    except Exception as e:
        app.logger.error(f"Error processing file: {str(e)}")
        // 返回500错误码,触发AJAX的error回调
        return render_template('error_type.html', title='Unable to process uploaded budget.'), 500

方案说明

  1. AJAX异步上传避免了页面跳转,可实时监听请求的成功/失败状态;
  2. 以blob格式接收文件数据,手动创建下载链接触发浏览器下载,完全可控;
  3. 下载完成后立即执行页面刷新,刷新时机与下载动作强绑定,不受任务耗时影响;
  4. 错误场景下会跳转到错误页面,同时可在complete回调中处理加载状态的隐藏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 12:48:29