将解码后的临时图像保存到Django ImageField。

6
我会尽力帮忙翻译中文。以下是需要翻译的内容:

我正在尝试将以Base64编码的文本形式传递给我的图像保存到Django Imagefield中。

但是似乎无法正确保存。数据库报告说所有我的图像都被存储为"",而不是应该报告它们的文件名,例如:

"template_images/template_folders/myImage.png"

试图保存我的图像的代码如下:
elif model_field.get_internal_type() == "ImageField" or model_field.get_internal_type() == "FileField":  # Convert files from base64 back to a file.
    if field_elt.text is not None:
        setattr(instance, model_field.name, File(b64decode(field_elt.text)))
3个回答

28

阅读这个答案后,我让它起作用了:

from base64 import b64decode
from django.core.files.base import ContentFile

image_data = b64decode(b64_text)
my_model_instance.cool_image_field = ContentFile(image_data, 'whatup.png')
my_model_instance.save()
因此,我建议你将你的代码更改为:

from django.core.files.base import ContentFile

# Your other code...

elif model_field.get_internal_type() == "ImageField" or model_field.get_internal_type() == "FileField":  # Convert files from base64 back to a file.
    if field_elt.text is not None:
        image_data = b64decode(field_elt.text)
        setattr(instance, model_field.name, ContentFile(image_data, 'myImage.png'))

假设你的 ImageField 使用了 upload_to 参数,并设置为 template_images / template_folders / ,那么你应该能看到文件保存到 YOUR_MEDIA_URL/template_images/template_folders/myImage.png


我尝试遵循相同的方法,但在解码时出现“填充不正确”的错误。有什么建议吗? - Mutant
3
好的,我会尽力进行翻译。以下是需要翻译的内容:Yup, you don't want to include the initial data:image/gif;base64, bit but then I guess you probably know that by now, just for the people that came here via Google like I did.是的,你不需要包含最开始的data:image/gif;base64, 这一部分,但我想你现在可能已经知道了,这句话只是为了那些像我一样通过谷歌来到这里的人提供帮助。 - xxx
我认为这个可能会失败,因为您不需要包含文件的 data:image/*;base64, 部分。 - Shift 'n Tab

2

另一种很好的方法基于这个SO答案:https://dev59.com/H14c5IYBdhLWcg3wVpFI#28036805,我尝试过并在django 1.10中进行了测试。

我创建了一个解码base64文件的函数。

def decode_base64_file(data):

    def get_file_extension(file_name, decoded_file):
        import imghdr

        extension = imghdr.what(file_name, decoded_file)
        extension = "jpg" if extension == "jpeg" else extension

        return extension

    from django.core.files.base import ContentFile
    import base64
    import six
    import uuid

    # Check if this is a base64 string
    if isinstance(data, six.string_types):
        # Check if the base64 string is in the "data:" format
        if 'data:' in data and ';base64,' in data:
            # Break out the header from the base64 content
            header, data = data.split(';base64,')

        # Try to decode the file. Return validation error if it fails.
        try:
            decoded_file = base64.b64decode(data)
        except TypeError:
            TypeError('invalid_image')

        # Generate file name:
        file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
        # Get the file name extension:
        file_extension = get_file_extension(file_name, decoded_file)

        complete_file_name = "%s.%s" % (file_name, file_extension, )

        return ContentFile(decoded_file, name=complete_file_name)

然后你可以调用这个函数。
import decode_base64_file

p = Post(content='My Picture', image=decode_based64_file(your_base64_file))
p.save()

1
我想这是最干净和最简短的方法。
以下是在基于Django(也包括drf)API端处理Base64编码图像文件并将其保存为ImageField的方法。
假设您有一个如下所示的模型:
Class MyImageModel(models.Model):
      image = models.ImageField(upload_to = 'geo_entity_pic')
      data=model.CharField()

因此,相应的序列化程序将如下所示:
 from drf_extra_fields.fields import Base64ImageField

 Class MyImageModelSerializer(serializers.ModelSerializers):
      image=Base64ImageField()
      class meta:
         model=MyImageModel
         fields= ('data','image')
      def create(self, validated_data):
        image=validated_data.pop('image')
        data=validated_data.pop('data')
       return MyImageModel.objects.create(data=data,image=image)

相应的视图可以如下所示:
elif request.method == 'POST':
    serializer = MyImageModelSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=201)
    return Response(serializer.errors, status=400)

注意,在序列化器中我使用了django-extra-field模块提供的Base64ImageField实现。

要安装此模块,请运行以下命令:

pip install pip install django-extra-fields

导入相同的内容,完成!

将您的图像作为Base64编码字符串通过JSON对象发送(通过post方法),同时附带任何其他数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接