私のアップロード フォームは tar ファイルを想定しており、アップロードされたデータが有効かどうかを確認したいと考えています。tarfileモジュールは をサポートしていis_tarfile()
ますが、ファイル名が必要です。ファイルが有効かどうかを確認するためだけに、ファイルをディスクに書き込んでリソースを浪費したくありません。
標準の Python ライブラリを使用して、ディスクに書き込むことなく、データが有効な tar ファイルであることを確認する方法はありますか?
私のアップロード フォームは tar ファイルを想定しており、アップロードされたデータが有効かどうかを確認したいと考えています。tarfileモジュールは をサポートしていis_tarfile()
ますが、ファイル名が必要です。ファイルが有効かどうかを確認するためだけに、ファイルをディスクに書き込んでリソースを浪費したくありません。
標準の Python ライブラリを使用して、ディスクに書き込むことなく、データが有効な tar ファイルであることを確認する方法はありますか?
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 スペース (10 進値 32) である 8 つのチェックサム バイトの合計を取得することによって計算されます。
これは、先行ゼロ、ヌル、スペースの順に続く 6 桁の 8 進数として格納されます。
さまざまな実装がこれに準拠していないため、最初の空白を 6 桁で切り取ったチェックサムに依存すると、互換性が向上します。さらに、一部の歴史的な tar 実装では、バイトを署名済みとして扱いました。
リーダーは両方の方法でチェックサムを計算し、署名付きまたは署名なしのいずれかの合計が含まれているチェックサムと一致する場合、それを適切に処理する必要があります。
UStar 形式もあります (リンク先にも詳しく説明されています) が、これは古い tar 形式の拡張であるため、上記で説明した方法は引き続き機能するはずです。UStar は通常、各ファイルに関する追加情報を保存するためのものです。
または、Python はオープン ソースでis_tarfile
あるため、ファイルではなくストリームをチェックするように動作を確認し、適応させることができます。ソースコードは以下から入手できますPython-3.1.1/Lib/tarfile.py
が、気弱な人向けではありません:-)
クラス TarFile は fileobj オブジェクトを受け入れます。Web フレームワークから取得した部分ダウンロード エンティティを渡すことができると思います。
__init__(self, name=None, mode='r', fileobj=None)
paxdiablo の投稿への追加: tar は、見た目はシンプルですが、非常に難しく複雑なファイル形式です。基本的な制約を確認できますが、考えられる既存の tar 方言をすべてサポートする必要がある場合は、多くの時間を浪費することになります。その複雑さのほとんどは、次の問題に起因します。
また、この形式には事前ヘッダーがないため、アーカイブ全体が正常かどうかを確認する唯一の方法は、ファイルを完全にスキャンし、各レコードをキャッチして、それぞれを検証することです。
のopen
メソッドtarfile
は、ファイルのようなオブジェクトをfileObj
引数に取ります。これはStringIO
インスタンスになることができます
アップロードされたデータが string に含まれているとします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のドキュメントを参照してください。