2013-02-27 73 views
6

我试图将传递给我的图像作为Base64编码文本保存到Django Imagefield中。将解码的临时图像保存到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))) 

回答

24

看完后this answer,我得到这个工作:

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')) 

然后,假设你ImageFieldupload_to参数设置为template_images/template_folders/定义,你应该看到的文件保存下来,以YOUR_MEDIA_URL/template_images/template_folders/myImage.png

+0

我试图按照同样的办法,虽然我得到“不正确的填充”的解码。任何建议? – Mutant 2013-10-30 15:24:57

+3

是的,你不想包括最初的数据:image/gif; base64,但是我猜你现在可能知道,就像我那样通过Google来到这里的人。 – 2014-02-28 04:38:13

+0

我认为这可能会失败,因为你不需要包含'data:image/*; base64'文件的一部分。 – 2017-04-20 01:21:29

0

我想这是要做到这一点最干净和最简单的办法。

以下是如何在基于Django(drf也)API端的post请求中处理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) 

注意在串行器中,我已经使用了模块中提供的Base64ImageField的实现

要安装该模块运行命令

pip install pip install django-extra-fields 

导入相同,完成!

将您的图像作为JSON对象中的Base64编码字符串以及您拥有的任何其他数据发送(通过post方法)。

0

在此基础上SO回答另外一个好办法:https://stackoverflow.com/a/28036805/6143656尝试过了,在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()