【问题标题】:Preferred method for downloading a file generated on the fly in Flask在 Flask 中下载动态生成的文件的首选方法
【发布时间】:2011-03-23 19:02:13
【问题描述】:

我有一个显示目录中文件列表的页面。当用户单击“下载”按钮时,所有这些文件都被压缩成一个文件,然后提供下载。我知道如何在单击按钮时将此文件发送到浏览器,并且我知道如何重新加载当前页面(或重定向到不同的页面),但是是否可以在同一步骤中同时执行这两项操作?还是用下载链接重定向到不同的页面更有意义?

我的下载是使用 Flask API 的 send_from_directory 启动的。相关测试代码:

@app.route('/download', methods=['GET','POST'])
def download():
    error=None
    # ...

    if request.method == 'POST':
        if download_list == None or len(download_list) < 1:
            error = 'No files to download'
        else:
            timestamp = dt.now().strftime('%Y%m%d:%H%M%S')
            zfname = 'reports-' + str(timestamp) + '.zip'
            zf = zipfile.ZipFile(downloaddir + zfname, 'a')
            for f in download_list:
                zf.write(downloaddir + f, f)
            zf.close()

            # TODO: remove zipped files, move zip to archive

            return send_from_directory(downloaddir, zfname, as_attachment=True)

    return render_template('download.html', error=error, download_list=download_list)

更新:作为一种解决方法,我现在通过单击按钮加载一个新页面,让用户在返回更新列表之前启动下载(使用 send_from_directory)。 p>

【问题讨论】:

    标签: html download flask


    【解决方案1】:

    您是否在 nginx 或 apache 等前端 Web 服务器后面运行烧瓶应用程序(这将是处理文件下载的最佳方式)。如果您使用的是 nginx,则可以使用 'X-Accel-Redirect' 标头。在本例中,我将使用目录 /srv/static/reports 作为您在其中创建压缩文件并希望从中提供它们的目录。

    nginx.conf

    server 部分

    server {
      # add this to your current server config
      location /reports/ {
        internal;
        root /srv/static;
      }
    }
    

    你的烧瓶方法

    将标头发送到 nginx 到服务器

    from flask import make_response
    @app.route('/download', methods=['GET','POST'])
    def download():
        error=None
        # ..
        if request.method == 'POST':
          if download_list == None or len(download_list) < 1:
              error = 'No files to download'
              return render_template('download.html', error=error, download_list=download_list)
          else:
              timestamp = dt.now().strftime('%Y%m%d:%H%M%S')
              zfname = 'reports-' + str(timestamp) + '.zip'
              zf = zipfile.ZipFile(downloaddir + zfname, 'a')
              for f in download_list:
                  zf.write(downloaddir + f, f)
              zf.close()
    
              # TODO: remove zipped files, move zip to archive
    
              # tell nginx to server the file and where to find it
              response = make_response()
              response.headers['Cache-Control'] = 'no-cache'
              response.headers['Content-Type'] = 'application/zip'
              response.headers['X-Accel-Redirect'] = '/reports/' + zf.filename
              return response
    

    如果你使用的是 apache,你可以使用他们的 sendfile 指令http://httpd.apache.org/docs/2.0/mod/core.html#enablesendfile

    【讨论】:

    • 谢谢 - 该应用程序将在 Apache 后面运行,我发现我可能应该使用 X-Sendfile 来提供文件。我的问题的另一部分是是否可以呈现模板(以更新显示的信息)并在同一步骤中返回文件响应。到目前为止,我的理解是它不是。
    猜你喜欢
    • 2019-06-23
    • 1970-01-01
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    • 2020-03-28
    • 1970-01-01
    相关资源
    最近更新 更多