【问题标题】:Is it safe to download a NamedTemporaryFile from a pyramid FileResponse?从金字塔 FileResponse 下载 NamedTemporaryFile 是否安全?
【发布时间】:2015-09-24 12:10:52
【问题描述】:

我目前正在使用 Python 上的 Pyramid 并在 Ubuntu 14.04 上运行的 Web 应用程序的导出功能。它将文件压缩到 NamedTemporaryFile 并通过 FileResponse 发回:

# Create the temporary file to store the zip
with NamedTemporaryFile(delete=True) as output:
    map_zip = zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED)
    length_mapdir = len(map_directory)

    for root, dirs, files in os.walk(map_directory, followlinks=True):
        for file in files:
            file_path = os.path.join(root, file)
            map_zip.write(file_path, file_path[length_mapdir:])

    map_zip.close()

    #Send the response as an attachement to let the user download the file
    response = FileResponse(os.path.abspath(output.name))
    response.headers['Content-Type'] = 'application/download'
    response.headers['Content-Disposition'] = 'attachement; filename="'+filename+'"'
    return response

在客户端,导出需要一些时间,然后出现文件下载弹出窗口,没有任何问题,一切都按计划在 zip 中。

压缩文件时,我可以看到 /tmp/ 中的文件越来越大,在出现下载弹出窗口之前,文件消失了。我假设这是 NamedTemporaryFile。

在压缩或下载文件时,使用的 RAM 量没有任何显着变化,它保持在 40mb 左右,而实际 zi​​p 超过 800mb。

金字塔从哪里下载文件?根据我对 tempfile 的了解,它在关闭时是未链接的。如果这是真的,是否有可能另一个进程可能会在存储文件的内存上写入数据,从而破坏正在下载的任何金字塔?

【问题讨论】:

标签: python pyramid


【解决方案1】:

在 Unix 环境中,在创建和打开文件时会使用一种称为引用计数的方法。对于文件上的每个open() 调用,参考编号会增加,对于每个close(),参考编号会减少。 unlink() 的特殊之处在于,当它被调用时,文件会从目录树中取消链接,但只要引用计数保持在 0 以上,它就会保留在磁盘上。

在您的情况下,NamedTemporaryFile() 在磁盘上创建一个名为 /tmp/somefile 的文件

  1. /tmp/somefile 现在的链接数为 1
  2. /tmp/somefile 然后调用了open(),以便它可以将文件返回给您,这会将引用计数增加到 1
  3. /tmp/somefile 然后由您的代码写入,在本例中为 zip 文件
  4. 然后将/tmp/somefile 传递给FileResponse(),然后调用open(),将引用计数增加到2
  5. 退出with 语句的范围,NamedTemporaryFile() 调用close(),后跟unlink()。您的文件现在有 1 个对它的引用,并且链接计数为 0。由于引用仍然存在,该文件仍然存在于磁盘上,但在搜索时不再可见。
  6. FileResponse() 被你的 WSGI 服务器迭代,最终一旦文件被完全读取,你的 WSGI 服务器调用 close() ,将引用计数降至 0,此时文件系统将完全清理文件

在最后一点,文件不再可访问。同时,您的文件是完全安全的,无法在内存中或其他方式覆盖它。

话虽如此,例如,如果 FileResponse() 是延迟加载的(即在 WSGI 服务器开始发送响应之前它不会 open() 文件),它完全有可能尝试 open()临时文件太迟了,NamedTemporaryFile() 已经删除了该文件。只是需要记住的一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-05
    • 2021-03-21
    • 2020-12-23
    • 2017-12-20
    • 2019-07-19
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    相关资源
    最近更新 更多