簡體   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