2013-02-27 72 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()