Как указать тип файла, возвращающего файл из flask? - PullRequest
1 голос
/ 03 августа 2020

В построении функции flask, которая отправляет файл пользователю для загрузки и удаляет файл сразу после его отправки. Мне удалось это сделать с помощью генератора. Однако при тестировании файл, отправленный пользователю, имеет совершенно другой формат (download.htm), чем исходный файл (.res). Как указать тип файла, чтобы он оставался в .res?

Вот что у меня есть:

@app.route('/download')
def download_file():

    file_pathres = dirname(realpath(__file__)) + '/' + pathres
    file_pathtxt = dirname(realpath(__file__)) + '/' + pathtxt

    print('download file path: ' + file_pathres)
    #file_path = derive_filepath_from_filename(filename)
    file_handle = open(file_pathres, 'r')

        # This *replaces* the `remove_file` + @after_this_request code above
    def stream_and_remove_file():
        yield from file_handle
        file_handle.close()
        os.remove(file_pathres)
        os.remove(file_pathtxt)

    return current_app.response_class(
        stream_and_remove_file(),
        headers={'Content-Disposition': 'attachment'}
    )

Что мне нужно изменить в заголовках или операторе возврата, чтобы убедиться, что отправка находится в тот же формат, что и у исходного файла, открытого и удаленного?

Ответы [ 2 ]

0 голосов
/ 04 августа 2020

Обнаружен обходной путь:

    r = current_app.response_class(stream_and_remove_file(), mimetype='text')
    r.headers.set('Content-Disposition', 'attachment', filename="filename.res")
    return r

Укажите тип файла в параметре имени файла при установке заголовков, принудительно отправляет файл в этом формате.

0 голосов
/ 03 августа 2020

Фактическое имя файла по умолчанию никогда не отправляется клиенту. A filename - это идентификатор, который поступает из ОС, а не какое-либо свойство самого файла. Это похоже на имя указателя, указывающего на место в памяти или на диске, где хранится содержимое этого файла. Когда вы отправляете файл через net, вы отправляете только его содержимое, необработанные данные вместе с некоторым информационным заголовком. Там вы можете указать директиву для клиента, чтобы установить имя файла в своей файловой системе, если хотите (как описано ниже).

Если не указано иное, браузер просто использует конечную точку запроса (/download) и некоторую информацию заголовка, такую ​​как параметр media-type (или MIME-Type) из заголовка Content-Type ответа, чтобы получить подходящее имя файла. В Flask класс Response по умолчанию устанавливает MIME-Type каждого ответа на text/html, если не указано иное ( источник ).

Итак, в вашем случае браузер принимает конечная точка /download в качестве имени файла и выбирает расширение в соответствии с MIME-Type, что составляет text/html => donwload.html

. Вы можете создать подкласс класса Response и настроить поведение по умолчанию, что повлияет на все ваши ответы, или вы можете установить имя файла (вместе с расширением), которое должно отображаться в диалоговом окне браузера «Сохранить как», с параметром filename в заголовке Content-Disposition каждый ответ:

return app.response_class(
  stream_and_remove_file(),
  headers={'Content-Disposition': "attachment; filename=testfile.res"}
)

Свойство attachment просто указывает браузеру загружать содержимое ответа в виде файла и не пытаться его отобразить.

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