6

私は、Turbogears 2 でファイルのアップロードを管理するための「ベスト プラクティス」の方法を模索してきましたが、これまで実際に例を見つけていません。ファイルを実際にアップロードする方法を見つけましたが、それがどれほど信頼できるかはわかりません。

また、アップロードされたファイル名を取得する良い方法は何でしょうか?

    file = request.POST['file']
    permanent_file = open(os.path.join(asset_dirname,
        file.filename.lstrip(os.sep)), 'w')
    shutil.copyfileobj(file.file, permanent_file)
    file.file.close()
    this_file = self.request.params["file"].filename 
    permanent_file.close()

私が正しく理解していると仮定すると、このようなものはコアの「命名」の問題を回避できますか? ID = UUID。

    file = request.POST['file']
    permanent_file = open(os.path.join(asset_dirname,
        id.lstrip(os.sep)), 'w')
    shutil.copyfileobj(file.file, permanent_file)
    file.file.close()
    this_file = file.filename
    permanent_file.close()
4

6 に答える 6

3

Allesandro Molinaの優れたライブラリーDepotがこの質問に対する最良の答えを構成していることを知っておいてください。

ネーミングとコピーの問題の両方を解決し、TurboGears アプリケーションにうまく組み込むことができます。次の例のように、MongoDB GridFS で使用できます。

from depot.manager import DepotManager

# Configure a *default* depot to store files on MongoDB GridFS
DepotManager.configure('default', {
    'depot.backend': 'depot.io.gridfs.GridFSStorage',
    'depot.mongouri': 'mongodb://localhost/db'
})

depot = DepotManager.get()

# Save the file and get the fileid
fileid = depot.create(open('/tmp/file.png'))

# Get the file back
stored_file = depot.get(fileid)
print stored_file.filename
print stored_file.content_type

または、次のように、 SQLAlchemyモデルに添付フィールドを簡単に作成できます。

from depot.fields.sqlalchemy import UploadedFileField

class Document(Base):
    __tablename__ = 'document'

    uid = Column(Integer, autoincrement=True, primary_key=True)
    name = Column(Unicode(16), unique=True)

    content = Column(UploadedFileField)

…そして、添付ファイル (ソースはファイルまたはバイトの場合があります) を含むドキュメントの保存は、次のように簡単になります。

doc = Document(name=u'Foo', content=open('/tmp/document.xls'))
DBSession.add(doc)

Depot はLocalFileStorageMongoDBGridFSStorageと Amazon の両方をサポートしていますS3Storage。そして、少なくともローカルおよび S3 に保存されているファイルについてはfileiduuid.uuid1().

于 2015-04-20T09:39:58.093 に答える
2

Turbogears について、また、次のことを回避するために何かを提供できるかどうかについてはよくわかりませんが、このコードには危険が伴うように思えます。悪意のあるユーザーが、Turbogears python プロセスが書き込みアクセス権を持つファイルを上書き (または作成) する可能性があります。

asset_dirnameis 、is/tmpの内容、および file の内容 UNIX 環境では、このコード (パーミッション保留中) はファイルを切り捨てモードで開き、アップロードされたファイルの内容をそれにコピーします。これにより、システムのパスワード ファイルが効果的に上書きされ、パスワードなしで root ユーザーが指定されます。おそらく、Windows マシンに対しても実行できる厄介なことがあります。file.filename../../../../../../../etc/passwdroot::0:0:root:/root:/bin/bash/tmp/../../../../../../../etc/passwd

OK、これは python が as で実行されていることを必要とする極端な例ですroot(誰もそれをしていませんよね?)。Python が権限の低いユーザーとして実行されている場合でも、以前にアップロードされたファイルが勝手に上書きされる可能性があります。

要約すると、ユーザー入力を信頼しないでください。この場合、ユーザーが提供したファイル名は で使用できますfile.filename

于 2010-03-04T02:04:53.957 に答える
2

@mhawke - あなたがそれを処理しなければならないのは正しいです - ファイルで何をしているかによって異なります.問題、またはファイル名が実際にはファイルの内容だけでなく、それでも悪い習慣である場合。

名前付きの tempfile を tmp dir で使用し、検証後にファイルを最終的な場所に移動できます。または、次のようにファイル名がまだ存在しないことを確認できます。

file.name = slugify(myfile.filename)
name, ext = os.path.splitext(file.name)
while os.path.exists(os.path.join(permanent_store, file.name)):
    name += '_'
    file.name = name + ext

raw_file = os.path.join(permanent_store, file.name)

slugify メソッドは、ファイル名を整理するために使用されます...

于 2010-03-05T08:07:43.223 に答える
0

ターボギアはただのパイロンにエキストラを付けただけじゃないの?そこのヘルプをチェックアウトできます:

http://wiki.pylonshq.com/display/pylonsdocs/Form+Handling#file-uploads

ただし、これには mhawke が言及した潜在的なセキュリティ上の欠陥が含まれています。

os.path.join(permanent_store, myfile.filename.lstrip(os.sep))

上記と同じように、ファイル名が何らかの形であっ../../../../../etc/passwdた場合、そのファイルを置き換えることができます...

したがって、次のように実際のファイル名を取得できます。

os.path.join(permanent_store, myfile.filename.split(os.sep).pop())
于 2010-03-04T09:06:35.940 に答える
0

Werkzeug には、 secure_filenameと呼ばれるファイル名を保護するための非常に優れたヘルパー関数があります。取り入れて使っていただけると思います。

于 2010-03-08T10:05:47.603 に答える