Предпочтительный способ загрузки файла, сгенерированного на лету во Flask - PullRequest
14 голосов
/ 23 марта 2011

У меня есть страница, которая отображает список файлов в каталоге. Когда пользователь нажимает кнопку «Загрузить», все эти файлы упаковываются в один файл, который затем предлагается для загрузки. Я знаю, как отправить этот файл в браузер, когда кнопка нажата, и я знаю, как перезагрузить текущую страницу (или перенаправить на другую), но возможно ли сделать и то и другое за один шаг? Или более целесообразно перенаправить на другую страницу со ссылкой для скачивания?

Моя загрузка инициируется с помощью API-интерфейса Flask 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), прежде чем вернуться к обновленному списку.

1 Ответ

7 голосов
/ 28 марта 2011

Запускаете ли вы приложение фляги за интерфейсным веб-сервером, таким как nginx или apache (который будет лучшим способом для загрузки файлов).Если вы используете nginx, вы можете использовать заголовок 'X-Accel-Redirect' .В этом примере я буду использовать каталог /srv/static/reports в качестве каталога, в котором вы создаете zip-файлы и хотите обслужить их.

nginx.conf

в разделе server 1011 *

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...