【问题标题】:Flask send_file function triggered by inline JS but does not actually return the send_file内联 JS 触发的 Flask send_file 函数但实际上并没有返回 send_file
【发布时间】:2021-07-04 19:44:42
【问题描述】:

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

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

以该帖子为指导,我的代码如下所示:

app.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')

waiting.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请求返回一个重定向函数到另一个url。此外,.zip 文件已正确生成,并且文件也已正确下载和处理。 Flask 和 Python 都不会引发任何错误。

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

为了让 Flask 返回我的 .zip,我缺少什么?非常感谢任何 cmets!

【问题讨论】:

    标签: javascript python flask


    【解决方案1】:

    感谢这篇帖子Flask send_file as attachment not working 我能够弄清楚发生了什么。

    由于 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>
    

    【讨论】:

      猜你喜欢
      • 2022-01-21
      • 2023-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      • 1970-01-01
      • 1970-01-01
      • 2017-09-24
      相关资源
      最近更新 更多