如何指定从烧瓶返回文件的文件类型?

时间:2020-08-03 06:33:58

标签: python http flask http-headers

我正在构建一个flask函数,该函数将文件发送给用户进行下载,并在文件发送后迅速将其删除。我设法用发电机做到了。但是,在测试中,发送给用户的文件与原始文件(.res)的格式完全不同(download.htm)。如何指定要保留在.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'}
    )

我应该在标题或return语句中进行哪些更改,以确保发送的格式与最初打开和删除的文件的格式相同?

2 个答案:

答案 0 :(得分:0)

默认情况下,实际文件名永远不会发送到客户端。 filename是来自操作系统的标识符,而不是文件本身的某些属性。就像指针的名称一样,它指向内存或驱动器上存储该文件内容的位置。通过网络发送文件时,仅发送其内容,原始数据以及一些信息标头。如果需要,您可以在此处指定一个指令,供客户端在其文件系统上设置文件名(如下所述)。

如果没有其他指定,浏览器将仅使用请求的端点(/download)和来自{{3}的media-type(或MIME-Type)参数之类的标头信息}响应的标题以提供适当的文件名。在Flask中,默认Response类将每个响应的MIME-Type设置为text/html,如果没有另外指定(Content-Type)。

因此,在您的情况下,浏览器将端点/download作为文件名,并根据MIME-Type选择扩展名,即text/html => donwload.html

您可以继承Response类并自定义默认行为,这会影响您的所有响应,也可以设置应在浏览器中“另存为”中显示的文件名(以及扩展名)。对话框,每个响应的source标头中的filename参数:

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

attachment属性仅告诉浏览器将响应内容下载为文件,而不尝试呈现它们。

答案 1 :(得分:0)

找到了解决方法:

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

设置标题时,请在filename参数中指定文件类型,强制发送文件为该格式。