为什么表格中的ImageField总是触发" invalid_image"?

时间:2015-12-11 13:00:04

标签: python django django-models django-forms

我已使用Django 1.8中的枕头验证实施了ImageField上传图片。出于某种原因,我无法提交表格。它总是在表单中引发这个ValidationError(但是使用FileField会起作用):

  

上传有效图片。您上传的文件不是图像或损坏的图像。

所有这一切的奇怪之处在于ImageField.check方法似乎获得了正确的MIME类型! (见下文)

我做了什么

我尝试过JPG,GIF和PNG格式;没人工作。

所以我尝试在django.forms.fields.ImageField中修改一些变量来修改触发此错误的try语句,添加用于测试的print语句:

try:
    # load() could spot a truncated JPEG, but it loads the entire
    # image in memory, which is a DoS vector. See #3848 and #18520.
    image = Image.open(file)
    # verify() must be called immediately after the constructor.
    damnit = image.verify()
    print 'MY_LOG: verif=', damnit

    # Annotating so subclasses can reuse it for their own validation
    f.image = image
    # Pillow doesn't detect the MIME type of all formats. In those
    # cases, content_type will be None.
    f.content_type = Image.MIME.get(image.format)
    print 'MY_LOG: image_format=', image.format
    print 'MY_LOG: content_type=', f.content_type

然后我再次提交表单以在运行python manage.py runserver后触发错误并获取以下行:

  

MY_LOG:verif =无

     

MY_LOG:image_format = JPEG

     

MY_LOG:content_type = image / jpeg

Pillow正确识别图像,并且执行try语句直到它的最后一行......仍然触发except语句?它使nosense!

使用相同的策略,我试图从django.db.models.fields.files.ImageField及其所有父母那里获取有用的日志,直到Field打印错误列表...所有这些都是空的!

我的问题

还有什么我可以尝试发现触发ValidationError的内容吗?

某些代码

models.py

class MyImageModel(models.Model):
    # Using FileField instead would mean succesfull upload
    the_image = models.ImageField(upload_to="public_uploads/", blank=True, null=True)

views.py

from django.views.generic.edit import CreateView
from django.forms.models import modelform_factory

class MyFormView(CreateView):
    model = MyImageModel
    form_class = modelform_factory(MyImageModel,
                 widgets={}, fields = ['the_image',])

编辑:

在尝试了@Alasdair建议的策略后,我从e.message获得了此报告:

  

无法识别图像文件< _io.BytesIO对象位于0x7f9d52bbc770>

但是,即使我不允许提交表单,该文件也会成功上传。看起来,如果不正确地处理图像的路径(或者阻碍这些行中图像加载的其他东西)。

我认为某些内容可能会失败(来自django.forms.fields.ImageField):

# We need to get a file object for Pillow. We might have a path or we might
# have to read the data into memory.
if hasattr(data, 'temporary_file_path'):
    file = data.temporary_file_path()
else:
    if hasattr(data, 'read'):
        file = BytesIO(data.read())
else:
    file = BytesIO(data['content'])

如果我探索这个类BytesIO有哪些属性,也许我可以提取一些有关错误的相关信息......

EDIT2

data属性空了!确定为什么不容易......

2 个答案:

答案 0 :(得分:1)

来自django文档:

  

使用ImageField要求安装Pillow并支持您使用的图像格式。如果您在上传图片时遇到corrupt image错误,通常意味着Pillow不了解其格式。要解决此问题,请安装相应的库并重新安装Pillow。

首先,你应该安装Pillow,而不是PIL(枕头是PIL的叉子),其次,在安装时,确保安装Pillow各种图像格式“理解”所需的所有库。

有关依赖项列表,您可以查看Pillow文档。

答案 1 :(得分:0)

经过深思熟虑,分析隐含的代码和大量的反复试验后,我尝试从我在问题中公开的while(whatever) { if(some_condition) { if(condition1) do_something1(); else if(condition2) do_something2(); else if(condition3) do_something3(); else if(condition4) do_something4(); /* more than two hundred more `else if` */ } } 块中编辑此行(在try / except中)这样:

django.forms.fields.ImageField

这解决了我的问题。现在一切正常,我可以提交表格。相应的# Before edition image = Image.open(file) # After my edition image = Image.open(f)

正确拒绝了无效文件

关于如何发生这个问题

我不确定我是否猜对了,但是:

  

我认为这很有效,因为这行命名正确的变量有错误。此外,使用ValidationError作为变量名称看起来像是一个错字,因为file似乎是为现有的内置保留的。{/ p>

如果我的猜测是正确的,也许我应该向Django开发人员报告此问题