使用Turbogears 2上载文件

2024-05-16 00:26:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在尝试用TurboGears2管理文件上传的“最佳实践”方法,但到目前为止还没有找到任何实例。我已经想出了一种方法来上传这个文件,但我不确定它有多可靠。在

另外,什么是一个好的方法来获得上传的文件名?在

    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。在

^{pr2}$

Tags: 文件path实例方法closeos文件名request
3条回答

我不太了解Turbogears,也不知道它是否可以提供任何东西来避免以下情况,但在我看来,这个代码充满了危险。恶意用户可能会覆盖(或创建)Turbogears python进程具有写访问权限的任何文件。在

如果asset_dirname/tmpfile.filename的内容是{},而文件的内容是{},怎么办?在UNIX环境中,此代码(权限挂起)将在截断模式下打开文件/tmp/../../../../../../../etc/passwd,然后将上载文件的内容复制到该文件中-有效地覆盖系统的密码文件并指定一个没有密码的根用户。大概也有一些讨厌的事情可以对Windows机器做。在

好的,这是一个极端的例子,它要求python以root的形式运行(没有人这样做,是吗?)。即使python是以低权限用户身份运行的,以前上载的文件也可能被随意覆盖。在

总之,不要信任用户输入,在本例中是用户提供的文件名,该文件名在file.filename中可用。在

@mhawke-你是对的,你必须处理这个问题-这取决于你对文件的处理,如果名称冲突无关紧要,比如你只关心某些数据的最新版本,那么可能就没有问题了,或者文件名实际上并不重要,只是文件的内容,但这仍然是一种不好的做法。在

您可以在tmp dir中使用一个命名的tempfile,然后在验证之后将该文件移动到其最终位置。或者您可以检查文件名是否已经存在,如下所示:

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)

slagify方法将用于整理文件名。。。在

我只想让任何来这里寻找答案的人知道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模型中轻松创建附件字段,例如:

^{pr2}$

…然后,使用附加文件(源可以是文件或字节)存储文档变得非常简单:

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

Depot同时支持LocalFileStorageMongoDB^{}和Amazon的{a6}。并且,至少对于存储在本地和S3中的文件,fileid将由uuid.uuid1()生成。在

相关问题 更多 >