如何将svg文件上传到django应用程序?

ukdjmx9f  于 2023-07-01  发布在  Go
关注(0)|答案(2)|浏览(144)

我试图通过管理站点上传一个.svg到SQLite(django的默认数据库),我得到了以下错误:

Upload a valid image. The file you uploaded was either not an image or a corrupted image.

我可以上传.jpg文件,它工作正常。

class News(models.Model):
    news_id         = models.AutoField(primary_key=True, editable=False)
    news_title      = models.CharField(max_length=150)
    news_date       = models.DateTimeField(auto_now_add=True, editable=False)
    news_body       = models.TextField(max_length=1500)
    news_img        = models.ImageField(upload_to="pictures/%Y/%m/")
    news_author     = models.ManyToManyField(Author)

    class Meta:
        ordering: ['news_id']

    def __str__(self):
        return '%s %s %s'%(self.news_id, self.news_title, self.news_date)
hkmswyz6

hkmswyz61#

你应该将Django ImageField改为FileField,并将.svg扩展名添加到字段验证器。
文件扩展名验证程序
结果模型文件字段如下所示:

from django.core.validators import FileExtensionValidator

news_img = models.FileField(upload_to="pictures/%Y/%m/", validators=[FileExtensionValidator(['pdf', 'doc', 'svg'])])
rbl8hiat

rbl8hiat2#

创建自己的字段,如下所示:

import sys
from io import BytesIO
from PIL import Image
import xml.etree.cElementTree as et

from django.core.exceptions import ValidationError
from django.forms import ImageField as DjangoImageField
from django.utils import six

class SVGAndImageFormField(DjangoImageField):

    def to_python(self, data):
        """
        Checks that the file-upload field data contains a valid image (GIF, JPG,
        PNG, possibly others -- whatever the Python Imaging Library supports).
        """
        test_file = super(DjangoImageField, self).to_python(data)
        if test_file is None:
            return None

        # 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'):
            ifile = data.temporary_file_path()
        else:
            if hasattr(data, 'read'):
                ifile = BytesIO(data.read())
            else:
                ifile = BytesIO(data['content'])

        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(ifile)
            # verify() must be called immediately after the constructor.
            image.verify()

            # Annotating so subclasses can reuse it for their own validation
            test_file.image = image
            test_file.content_type = Image.MIME[image.format]
        except Exception:
            # add a workaround to handle svg images
            if not self.is_svg(ifile):
                six.reraise(ValidationError, ValidationError(
                    self.error_messages['invalid_image'],
                    code='invalid_image',
                ), sys.exc_info()[2])
        if hasattr(test_file, 'seek') and callable(test_file.seek):
            test_file.seek(0)
        return test_file

    def is_svg(self, f):
        """
        Check if provided file is svg
        """
        f.seek(0)
        tag = None
        try:
            for event, el in et.iterparse(f, ('start',)):
                tag = el.tag
                break
        except et.ParseError:
            pass
        return tag == '{http://www.w3.org/2000/svg}svg'

参考:https://gist.github.com/ambivalentno/9bc42b9a417677d96a21

相关问题