如何可靠地告诉上传的文件类型(文本或二进制)?

时间:2012-08-14 07:23:10

标签: python file-upload mime-types mime python-magic

我有一个应用程序,用户应该可以上传各种文件,但我需要知道每个文件,我是否可以安全地将其文本表示显示为纯文本。

使用python-magic之类的

m = Magic(mime=True).from_buffer(cgi.FieldStorage.file.read())

为我提供了正确的MIME类型。

但有时,脚本的MIME类型为application/*,因此仅仅查找m.startswith('text/')是不够的。

Another site建议使用

m = Magic().from_buffer(cgi.FieldStorage.file.read())

并检查'text' in m

第二种方法对于任意文件上传的集合是否足够可靠,或者有人可以给我另一个想法?

非常感谢。

2 个答案:

答案 0 :(得分:1)

你的目标是什么?你想要真正的哑剧吗?出于安全原因,这很重要吗?或者“很高兴”?

问题是同一个文件可以有不同的mime类型。当脚本文件具有正确的#!标头时,python-magic可以确定脚本类型并告诉您。如果标题丢失,text/plain可能是您获得的最佳内容。

这意味着没有通用的“将永远有效”的神奇解决方案(尽管模块的名称)。您将不得不坐下来思考您可以获得哪些信息,它意味着什么以及您希望如何对待它。

安全解决方案是创建一个您接受的mime类型列表,并使用以下命令检查它们:

allowed_mime_types = [ ... ]
if m in allowed_mime_types:

这意味着只接受完美的比赛。这也意味着您的服务器将拒绝由于某种原因没有正确的mime类型的有效文件(缺少标题,魔术无法识别文件,您忘记在列表中提及mime类型)。

或换句话说:如果你真的不在乎,为什么要检查文件的mime类型?

[编辑] 当你说

  

我需要知道每个文件,我是否可以安全地将其文本表示显示为纯文本。

然后这并不像听起来那么容易。首先,“文本”文件中没有存储编码,因此您需要知道用户在创建文件时使用的编码。这不是一项微不足道的任务。有启发式方法可以做到这一点,但是当使用ISO 8859-1和8859-15等编码时,事情变得毛茸茸(后者有欧元符号)。

要解决此问题,您需要强制用户以特定编码保存文本文件(UTF-8目前是最佳选择),或者您需要提供用户必须粘贴的表单文本。

使用表单时,用户可以看到文本是否编码正确(他们在屏幕上看到它),他们可以解决任何问题,您可以确保浏览器向您发送使用UTF-8编码的文本。

如果你不能这样做,你唯一的选择是检查输入中0x20以下的任何字节,\r\n\t除外。这是一个非常好的检查“这是一个文本文档”。

但是当用户使用变音符号时(比如当你编写一个全世界都在使用的应用程序时),这种方法最终会失败,除非你可以在用户一侧执行特定的编码(你可能不会这样做) t信任用户)。

[EDIT2] 因为你需要这个来检查实际的源代码:如果你想确保源代码是“安全的”,那么解析它。大多数语言允许解析代码而不实际执行它。这会给你一些真实的信息(因为解析器知道要查找什么),你不需要做出疯狂的猜测: - )

答案 1 :(得分:0)

在玩了一下后,我发现我可以使用Magic(mime_encoding=True)结果!

我在Dropbox文件夹上运行simple script,并按编码和扩展程序对结果进行分组,以检查是否存在违规行为。

但通过寻找'binary' in encoding确实看起来很有用。

我想我会坚持下去,但谢谢大家。

相关问题