如何使用magic来验证Django表单清理方法中的文件类型?

问题描述:

我已经用FileField在Django中编写了一个电子邮件表单类。我想通过检查它的mimetype来检查上传的文件的类型。随后,我想限制文件类型为pdf,word和open office文档。如何使用magic来验证Django表单清理方法中的文件类型?

为此,我已经安装了Python,魔术和想检查的文件类型为Python的魔法每次的规格如下:

mime = magic.Magic(mime=True) 
file_mime_type = mime.from_file('address/of/file.txt') 

然而,最近上传的文件没有在我的服务器地址。我也不知道类似于“from_file_content”的MIME对象的任何方法,该方法检查给定文件内容的MIME类型。

什么是使用魔法来验证Django表单中上传文件的文件类型的有效方法?

Stan用缓冲区描述了很好的变体。不幸的是,这种方法的弱点是将文件读到内存中。另一种选择是使用temporary stored file

import tempfile 
import os 

tmp_file_name = request.FILES['my_file_field'].name 
tmp_file_dir = tempfile.gettempdir() # usually /tmp on Unix 
tmp_file_path = os.path.join(tmp_file_dir, tmp_file_name) 

mime = magic.Magic(mime=True) 
file_mime_type = mime.from_file(tmp_file_path) 

# then check mime and raise ValidationError if required 
+0

谢谢,当我用clean_data试试这个时,Django注意到文件/tmp/filename.doc是未定义的。你知道为什么吗? – dangerChihuahua007 2011-12-28 02:22:10

+0

以某种方式或另一种方式,您的文件将被加载到内存中。我更喜欢避免直接玩临时路径。 – Stan 2011-12-28 02:30:30

+0

@Chi Zeng请提供您的看法和表格代码 – 2011-12-28 07:42:45

为什么不尝试类似的东西在你看来:

m = magic.Magic() 
m.from_buffer(request.FILES['my_file_field'].read()) 

或将要与记忆更好:

m.from_buffer(request.FILES['my_file_field'].chunks()) 

不好意思啊,刚才看到你想在你的表单验证,但是您应该使用cleaned_data表单的属性。

+0

第二个代码不正确。 'multiple_chunks()'不*返回块,它返回一个布尔值:文件是否足够大,可以分块。 https://docs.djangoproject.com/en/1.5/topics/http/file-uploads/#django.core.files.uploadedfile.UploadedFile.multiple_chunks – zopieux 2014-01-25 22:27:58

+0

@Zopieux:固定,谢谢。 – Stan 2014-01-26 10:39:52

+1

'from_buffer'需要一个字符串缓冲区,而不是一个迭代器。由于迭代器没有'len()',所以AFAIK你的新代码将会失败并出现AttributeError。我没有看到任何漂亮的解决方案,除了手动拿第一块。 – zopieux 2014-01-27 18:36:40

mime = magic.Magic(mime=True) 

attachment = request.FILES['attachment'] 

if hasattr(attachment, 'temporary_file_path'): 
    # file is temporary on the disk, so we can get full path of it. 
    mime_type = mime.from_file(attachment.temporary_file_path()) 
else: 
    # file is on the memory 
    mime_type = mime.from_buffer(attachment.read()) 

您可以使用django-safe-filefield包来验证上传的文件扩展名匹配它的MIME类型。

from safe_filefield.forms import SafeFileField 

class MyForm(forms.Form): 

    attachment = SafeFileField(
     allowed_extensions=('xls', 'xlsx', 'csv') 
    )