ImageField中验证图像格式

ImageField中验证图像格式

本文介绍了如何在django ImageField中验证图像格式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的项目使用Python 2.7,PIL 1.1.7和Django 1.5.1。有一个ImageField可以为许多图像格式工作,包括bmp,gif,ico,pnm,psd,tif和pcx。然而,要求是只允许png或jpg图像。如何做?



更新。我知道我可以验证文件扩展名和http Content-Type头文件。但两种方法都不可靠。我问的是,是否有办法检查上传的文件内容是否是png / jpg。

解决方案

你不指定是否使用Django表单上传图像,我认为这是在表单域中执行验证。



你可以做什么创建一个 django.forms.fields.ImageField 的子类来扩展to_python的功能。



文件类型检查目前在Django中执行的 to_python 看起来像这样

 图像。打开(文件).verify()

你的子类可以看起来像。
$ b

  class DmitryImageField(ImageField):

def to_python(self,data):
f = super(DmitryImageField,self ).to_python(data)
如果f是None:
return None

try:
来自PIL import Image
除了ImportE rror:
import Image

#我们需要获取PIL的文件对象。我们可能有一条路径,或者我们可能
#必须将数据读入内存。
if hasattr(data,'temporary_file_path'):
file = data.temporary_file_path()
else:
如果hasattr(data,'read'):
file = BytesIO(data.read())
else:
file = BytesIO(data ['content'])

try:
im = Image.open文件)
如果im.format不在('BMP','PNG','JPEG'):
raise ValidationError(不支持图像类型,请上传bmp,png或jpeg)
除了ImportError:
#在PyPy下,可以导入PIL。但是,底层的
#_imaging C模块不可用,所以ImportError将会被
#引发。抓住并重新加注
raise
除了异常:#Python Imaging Library不会将其识别为图像
raise ValidationError(self.error_messages ['invalid_image'])

如果hasattr (f,'seek')和callable(f.seek):
f.seek(0)
return f

您可能会注意到,这是来自 ImageField.to_python 的大部分代码,可能更喜欢只创建一个FileField的子类来使用而不是 ImageField 而不是子类化 ImageField 并复制其大部分功能。在这种情况下,请确保在格式检查之前添加 im.verify()



编辑:我应该指出我没有测试过这个子类。


Our project uses Python 2.7, PIL 1.1.7 and Django 1.5.1. There is an ImageField which works OK for many image formats, including bmp, gif, ico, pnm, psd, tif and pcx. However the requirement is to only allow png or jpg images. How can it be done?

Upd. I know I can validate file extension and http Content-Type header. But neither method is reliable. What I'm asking is whether there's a way to check uploaded file content for being png/jpg.

解决方案

You don't specify whether you're using a Django form to upload the image, I assume so as it is in the form field that the validation is carried out.

What you could do is create a subclass of django.forms.fields.ImageField to extend the functionality of to_python.

The file type check currently carried out in Django in to_python looks like this

Image.open(file).verify()

Your subclass could look something like.

class DmitryImageField(ImageField):

    def to_python(self, data):
        f = super(DmitryImageField, self).to_python(data)
        if f is None:
            return None

        try:
            from PIL import Image
        except ImportError:
            import Image

        # We need to get a file object for PIL. 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'])

        try:
            im = Image.open(file)
            if im.format not in ('BMP', 'PNG', 'JPEG'):
                raise ValidationError("Unsupport image type. Please upload bmp, png or jpeg")
        except ImportError:
            # Under PyPy, it is possible to import PIL. However, the underlying
            # _imaging C module isn't available, so an ImportError will be
            # raised. Catch and re-raise.
            raise
        except Exception: # Python Imaging Library doesn't recognize it as an image
            raise ValidationError(self.error_messages['invalid_image'])

        if hasattr(f, 'seek') and callable(f.seek):
            f.seek(0)
        return f

You may notice this is most of the code from ImageField.to_python and might prefer to just create a sub-class of FileField to use instead of ImageField rather than subclassing ImageField and duplicating much of its functionality. In this case make sure to add im.verify() before the format check.

EDIT: I should point out that I've not tested this subclass.

这篇关于如何在django ImageField中验证图像格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-31 05:42