使用 Turbogears 2 上传文件
我一直在尝试找出使用 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()
I've been trying to work out the 'best practices' way to manage file uploads with Turbogears 2 and have thus far not really found any examples. I've figured out a way to actually upload the file, but I'm not sure how reliable it us.
Also, what would be a good way to get the uploaded files name?
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()
So assuming I'm understanding correctly, would something like this avoid the core 'naming' problem? 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()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我只是希望任何来这里寻找答案的人都知道 Allesandro Molina 的伟大图书馆Depot 构成了这个问题的最佳答案。
它解决了命名和复制问题,并且可以很好地融入您的 TurboGears 应用程序中。您可以将其与 MongoDB GridFS 一起使用,如下例所示:
或者您可以轻松地在 SQLAlchemy 模型中创建附件字段,例如:
…然后,存储带有附加文件的文档(源可以是文件或字节)变得像这样简单:
Depot 同时支持
LocalFileStorage
、MongoDB 的GridFSStorage
,以及亚马逊的S3Storage
。并且,至少对于存储在本地和 S3 中的文件,fileid
将由uuid.uuid1()
生成。I just want anyone who comes here looking for answers, to know that Allesandro Molina's great library Depot constitutes the best answer to this question.
It solves both the naming and copying issues, and it will incorporate nicely into your TurboGears application. You can use it with MongoDB GridFS, as in this example:
or you can easily create attachment fields in your SQLAlchemy models, like:
… and then, storing documents with attached files (the source can be a file or bytes) becomes as easy as:
Depot supports both
LocalFileStorage
, MongoDB'sGridFSStorage
, and Amazon'sS3Storage
. And, at least for files stored locally and in S3, thefileid
will be generated byuuid.uuid1()
.@mhawke - 你是对的,你必须处理这个问题 - 取决于你对文件所做的事情,如果名称冲突并不重要,例如你只关心某些数据的最新版本,那么可能没有问题,或者如果文件名实际上并不重要,只是文件内容,但它仍然是不好的做法。
您可以在 tmp 目录中使用命名的临时文件,然后在验证后将该文件移动到其最终位置。或者您可以检查文件名是否已经存在,如下所示:
slugify 方法将用于整理文件名...
@mhawke - you're right you have to handle that - depends on what you are doing with the file, if it doesn't matter if there is a name collision eg you only care for the latest version of some data then theres probably no issue, or if the filename isn't actually important just the file contents, but its still bad practice.
You could use a named tempfile in a tmp dir, then move the file once validated to its final location. Or you could check the filename doesn't already exist like so:
The slugify method would be used to tidy up the filename...
我不太了解 Turbogears 以及它是否可以提供任何东西来避免以下情况,但在我看来,这段代码充满了危险。恶意用户可能会覆盖(或创建)Turbogears python 进程具有写访问权限的任何文件。
如果
asset_dirname
是/tmp
,file.filename
的内容是../../../../ ../../../etc/passwd
和文件root::0:0:root:/root:/bin/bash
的内容?在 UNIX 环境中,此代码(权限待定)将以截断方式打开文件/tmp/../../../../../../../etc/passwd
模式,然后将上传文件的内容复制到其中 - 有效地覆盖系统的密码文件并指定没有密码的 root 用户。想必 Windows 机器也可以做一些令人讨厌的事情。好的,这是一个极端的例子,要求 python 以 root 身份运行(没有人这样做,不是吗?)。即使Python以低权限用户运行,之前上传的文件也可能被随意覆盖。
总而言之,不要信任用户输入,在本例中,用户提供的文件名在
file.filename
中可用。I don't know much about Turbogears and whether it can provide anything to avoid the following, but it seems to me that this code is fraught with danger. It may be possible for a malicious user to overwrite (or create) any file that the Turbogears python process has write access to.
What if
asset_dirname
is/tmp
, the contents offile.filename
is../../../../../../../etc/passwd
and the contents of the fileroot::0:0:root:/root:/bin/bash
? In a UNIX environment this code (permissions pending) would open the file/tmp/../../../../../../../etc/passwd
in truncate mode and then copy the contents of the uploaded file to it - effectively overwriting your system's password file and specifying a root user without a password. Presumably there are nasty things that can be done to a Windows machine too.OK, this is an extreme example that requires that python is running as
root
(no one does that, do they?). Even if python is running as a low-priveleged user, previously uploaded files could be overwritten at will.To summarise, don't trust user input, in this case the user supplied filename that is available in
file.filename
.涡轮齿轮不就是带有附加装置的塔架吗?您可以查看那里的帮助:
http://wiki.pylonshq。 com/display/pylonsdocs/Form+Handling#file-uploads
但是,这仍然包含 mhawke 提到的潜在安全缺陷:
如果文件名某种程度上是
../../../ ,则与上面相同../../etc/passwd
然后你可以替换该文件...所以你可以像这样获取实际的文件名:
Isn't turbogears just pylons with extras? You could check out the help there:
http://wiki.pylonshq.com/display/pylonsdocs/Form+Handling#file-uploads
However, that still contains the potential security flaw that mhawke mentioned:
Same as above really if filename somehow was
../../../../../etc/passwd
then you could replace that file...So you could just get the actual filename like so:
Werkzeug 有一个非常好的帮助函数来保护文件名,名为 secure_filename< /a>.我认为您可以采用并使用它。
Werkzeug has a very good helper function for securing file names called secure_filename. I think you can adopt and use it.
关于如何走,我会赞同已经给出的好答案。
这是我关于存储文件命名的 2 便士。
事实上,使用原始名称保存文件可能会导致漏洞。
我对原始名称的唯一用途(如果有的话)是暗示 MIME 类型检测。
无论如何,要保存的文件应该通过记录标识或类似的东西指定唯一的名称,并保存在应用程序目录所有者(普通用户)控制下的位置,或保存在某些其他存储服务中,如上所述depot 等。
这是跨语言良好系统设计的问题:)。
about how to go, i'd second the good answers already given.
here's my 2 pence about the stored file naming.
indeed saving the file using the original name may cause a vulnerability.
the only use i make of the original name, if at all, is to hint the mime type detection.
anyway the files to be saved should be given unique names, by a record identity or something similar, and kept in a place under the control of the app directory owner, who is a regular user, or in some other storage service, as the aforementioned depot etc.
it's a matter of cross language good system design :).