如何确定数据是否为有效的tar文件,而不需要文件?

10

我的上传表单需要一个tar文件,我想检查上传的数据是否有效。tarfile模块支持is_tarfile(),但需要文件名 - 我不想浪费资源将文件写入磁盘只是为了检查它是否有效。

有没有一种方法可以使用标准Python库在不写入磁盘的情况下检查数据是否是有效的tar文件?

4个回答

5

tar文件格式在维基百科这里

我猜你最好的选择是检查第一个文件的头校验和是否有效。你可能还想检查文件名是否正确,但这可能不可靠,这取决于存储在其中的文件名。

在此复制相关信息:

Offset  Size  Description
     0   100  File name
   100     8  File mode
   108     8  Owner's numeric user ID
   116     8  Group's numeric user ID
   124    12  File size in bytes
   136    12  Last modification time in numeric Unix time format
   148     8  Checksum for header block
   156     1  Link indicator (file type)
   157   100  Name of linked file

校验和是通过将头块的无符号字节值相加并将八个校验和字节视为ASCII空格(十进制值32)来计算的。它存储为一个六位的八进制数,前面有前导零,然后是一个空字符和一个空格。由于一些历史悠久的tar实现将字节视为有符号的,因此各种实现都没有遵守这一规定,因此依赖于前六个去掉空格的数字进行校验和的方法能够更好地兼容。读者必须两种方式都计算校验和,并在有符号或无符号的和与所包含的校验和匹配时将其视为正确的。还有UStar格式(也在该链接中详细说明),但由于它是旧tar格式的扩展,因此上述方法仍然适用。UStar通常只用于存储有关每个文件的额外信息。
或者,由于Python是开源的,您可以查看is_tarfile如何工作并适应它来检查您的流而不是文件。源代码可在此处(Python-3.1.1/Lib/tarfile.py)获取,但这不适合新手。

有关编码非ASCII文件名的约定吗?那篇文章提到了问题,但没有提及解决方案。 - John Machin

3

TarFile类接受一个fileobj对象。我猜您可以传递从Web框架获取的任何部分下载实体。

__init__(self, name=None, mode='r', fileobj=None)

补充paxdiablo的帖子:tar是一种非常复杂和复杂的文件格式,尽管它看起来很简单。您可以检查基本约束条件,但如果您必须支持所有可能存在的tar方言,您将会浪费很多时间。其复杂性大部分来自以下问题:

  • 缺乏真正的标准,直到存在事实上的标准(UStar / pax)
  • 规范中存在漏洞,留下供应商灰色地带,每个供应商都实现了自己的解决方案
  • 供应商说“我们的tar更好,它将接管t3h世界”
  • 限制以及这些限制的解决方法(例如文件名长度)

此外,该格式没有预先的头文件,因此检查整个存档是否合理的唯一方法是完全扫描文件,捕获每个记录并验证每个记录。


啊,你比我快了半分钟 :-) - Eli Bendersky
不是很对,你的方法是另一种(可能更好)实现相同目标的方式。 - Stefano Borini

3

假设您上传的数据包含在字符串data中。

from tarfile import TarFile, TarError
from StringIO import StringIO

sio = StringIO(data)
try:
    tf = TarFile(fileobj=sio)
    # process the file....
except TarError:
    print "Not a tar file"

除了处理不同的tar文件格式和压缩,还存在其他复杂性。更多信息可在tarfile文档中找到。


这引出了一个问题:当直接检查文件时,Python的tarfile模块是否支持您所说的不同tar格式? - Brōtsyorfuzthrāx
2
@Shule 要回答这个问题,你可以查看 is_tarfile() 模块的源代码。 - mhawke

3
tarfileopen 方法接受一个类文件对象作为其 fileObj 参数。这可以是一个 StringIO 实例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接