17

ディレクトリ内のファイルのリストを表示するページがあります。ユーザーが[ダウンロード]ボタンをクリックすると、これらのファイルはすべて1つのファイルに圧縮され、ダウンロードできるようになります。ボタンがクリックされたときにこのファイルをブラウザに送信する方法と、現在のページをリロードする(または別のページにリダイレクトする)方法を知っていますが、同じ手順で両方を行うことは可能ですか?または、ダウンロードリンクを使用して別のページにリダイレクトする方が理にかなっていますか?

私のダウンロードはFlaskAPIで開始されます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は更新されたリストに戻る前に(を使用して)ダウンロードを開始できます。

4

1 に答える 1

8

nginxやapacheなどのフロントエンドWebサーバーの背後でflaskアプリを実行していますか(ファイルのダウンロードを処理するための最良の方法です)。nginxを使用している場合は、「X-Accel-Redirect」ヘッダーを使用できます。この例では/srv/static/reports、zipファイルを作成し、そこから提供したいディレクトリとしてディレクトリを使用します。

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を使用できます。

于 2011-03-28T18:06:45.777 に答える