2013-02-27 3 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')) 

Тогда, предполагая, что ваш ImageField определяется с upload_to аргументом, равным template_images/template_folders/, вы должны увидеть файл сохранить до YOUR_MEDIA_URL/template_images/template_folders/myImage.png

+0

Я пытался следовать такой же подход, хотя я получаю «Неправильное заполнение» на декодировании. Любое предложение? – Mutant

+3

Yup, вы не хотите включать исходные данные: image/gif; base64, бит, но потом, наверное, вы, наверное, знаете, что к настоящему времени просто для людей, которые пришли сюда через Google, как я. –

+0

Я думаю, что это может потерпеть неудачу, потому что вам не нужно включать 'data: image/*; base64,' часть файла. –

0

Я думаю, это самый чистый и самый короткий способ сделать это.

Вот как вы можете обрабатывать файл изображения с кодировкой Base64 в почтовом запросе на конце API-интерфейса, основанного на Django (drf), который сохраняет его как ImageField.

Пусть у вас есть модель следующим образом:

Class MyImageModel(models.Model): 
     image = models.ImageField(upload_to = 'geo_entity_pic') 
     data=model.CharField() 

Так Соответствуя Serializer будет следующим:

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, представленную в модуле django-extra-field

Чтобы установить этот модуль запустить команду

pip install pip install django-extra-fields 

Импортировать же и Готово!

Отправить (через метод post) ваше изображение в виде кодированной в Base64 строки в объекте JSON вместе с любыми другими данными, которые у вас есть.

0

Еще один хороший подход, основанный на этот SO ответ: https://stackoverflow.com/a/28036805/6143656 попробовал и испытаны в Джанго 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() 

 Смежные вопросы

  • Нет связанных вопросов^_^