繁体   English   中英

Flask send_file function 由内联 JS 触发但实际上并未返回 send_file

[英]Flask send_file function triggered by inline JS but does not actually return the send_file

关于我和问题的一些背景。 我不是 web 开发人员,也从未有过关于该主题的正式说明,所以我只是靠耳朵玩,并使用任何使它起作用的东西。 我正在使用 Flask 创建一个网站,当您传递某些信息时,它将返回一个包含您请求的文件的.zip 文件。 但是,该网站需要下载文件并对文件执行一些其他处理,因此这是一个耗时的过程,并且当我在 heroku 上托管我的应用程序时会超时。

为了绕过这个问题,我使用了这里描述的方法: Flask is not render_template before execution long function

使用该帖子作为指南,我的代码如下所示:

应用程序.py

@app.route('/long_function/<var1>/<var2>', methods=['GET', 'POST'])
def long_function(var1, var2):
    if request.method == 'POST':
        #Long task...
        return send_file(data, as_attachment=True, attachment_filename='data.zip')

    if request.method == 'GET':
         return render_template('waiting.html', var1=json.dumps(var1), var2=json.dumps(var2), return_to=json.dumps('/home')

等待。html

<script>
    var request = new XMLHttpRequest();
    request.open('POST', '/long_function/'+{{ var1|safe }} +'/'+ {{ var2|safe }});


    request.onload = function() {
      if (request.status === 200) {
        // long process finished successfully, redirect user
        window.location = {{ return_to|safe }};
      } else {
        // ops, we got an error from the server
        alert('Something went wrong.');
      }
    };

    request.onerror = function() {
      // ops, we got an error trying to talk to the server
      alert('Something went wrong.');
    };

    request.send();
</script>

有了这个,当我向long_function提交GET请求时,我立即得到一个有效的响应,即渲染waiting.html模板。 同时,在模板渲染的时候,JS脚本发送带有相应信息的POST请求,从而绕过了超时错误。

问题是 .zip 文件在完成长任务后永远不会发回给我。 Flask进程显示JS脚本发出的POST请求是有效的,测试时可以得到POST请求返回重定向function到另一个Z572D4E421E5E6B9BC12D815E8A027。 此外,.zip 文件生成正确,文件下载和处理也正确。 Flask 和 Python 都不会引发任何错误。

我猜测它与 JS 有关系,但我的 JS 知识几乎不存在,正如我之前所说,web 开发并不是我过于熟悉的东西。 我知道还有其他选项可以运行后台进程,例如 Celery,但我希望尽可能简单。

为了让 Flask 返回 my.zip,我缺少什么? 任何意见都非常感谢!

感谢这篇文章Flask 作为附件发送文件不起作用,我能够弄清楚发生了什么。

由于 POST 请求是使用 JS 通过浏览器发出的,因此 Flask 正在发送 .zip 文件作为对使用 JS 通过浏览器发出的请求的响应。 因此,我需要使用 JS 响应下载文件。 我能够使用这篇文章的答案Prompt file download with XMLHttpRequest 来完成它

结果,我waiting.html中的脚本现在看起来像这样:

<script>
    var request = new XMLHttpRequest();
    request.responseType = 'blob';
    request.open('POST', '/long_function/'+{{ var1|safe }} +'/'+ {{ var2|safe }});

    function saveBlob(blob, fileName) {
    var a = document.createElement('a');
    a.href = window.URL.createObjectURL(blob);
    a.download = fileName;
    a.dispatchEvent(new MouseEvent('click'));
}


    request.onload = function(e) {
      if (request.status === 200) {
        // long process finished successfully, redirect user
        var blob = e.currentTarget.response;
        saveBlob(blob, 'data.zip')
        window.location = {{ return_to|safe }};
      } else {
        // ops, we got an error from the server
        alert('Something went wrong.');
      }
    };

    request.onerror = function() {
      // ops, we got an error trying to talk to the server
      alert('Something went wrong.');
    };

    request.send();
</script>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM