2013-02-27 1 views
6

J'essaie d'enregistrer des images qui m'ont été transmises en tant que texte codé Base64 dans un champ Image de Django.Enregistrement d'une image temporaire décodée dans Django Imagefield

Mais il semble ne pas enregistrer correctement. Les rapports de base de données toutes mes images sont stockées sous forme de « » quand il doit les déclarer comme un nom de fichier par exemple:

"template_images/template_folders/myImage.png" 

Le code qui essaie de sauver mes images est la suivante:

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

Répondre

24

Après avoir lu this answer, je me suis cela fonctionne:

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

Par conséquent, je vous suggère de changer votre code:

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

Ensuite, en supposant que votre ImageField est défini avec l'argument upload_to mis à template_images/template_folders/, vous devriez voir le fichier de sauvegarde vers le bas pour YOUR_MEDIA_URL/template_images/template_folders/myImage.png

+0

J'ai essayé de suivre la même approche, bien que je reçois « capitonnage incorrect » sur decode. Toute suggestion? – Mutant

+3

Oui, vous ne voulez pas inclure les données initiales: image/gif; base64, mais je suppose que vous le savez probablement maintenant, juste pour les gens qui sont venus ici via Google comme je l'ai fait. –

+0

Je pense que celui-ci pourrait échouer parce que vous n'avez pas besoin d'inclure 'data: image/*; base64,' partie du fichier. –

0

Je suppose que cela est la manière la plus propre et la plus courte pour le faire.

Voici comment vous pouvez gérer un fichier image codé Base64 dans une demande de publication à l'extrémité de l'API basée sur Django (drf aussi) qui l'enregistre en tant que champ ImageField.

Disons que vous avez un modèle comme suit:

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

Ce serait comme sérialiseur correspondant suit:

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) 

La vue correspondante peut être comme suit:

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) 

Avis Dans le Serializer j'ai utilisé l'implémentation de Base64ImageField fournie dans le module django-extra-field

Pour installer ce module exécutez la commande

pip install pip install django-extra-fields 

Importation et même Fait!

Envoyez (via la méthode post) votre image sous la forme d'une chaîne codée Base64 dans un objet JSON, ainsi que toute autre donnée dont vous disposez.

0

Une autre bonne approche basée sur cette réponse SO: https://stackoverflow.com/a/28036805/6143656 essayé et testé dans django 1.10

J'ai fait une fonction pour le fichier base64 décodée.

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) 

Ensuite, vous pouvez appeler la fonction

import decode_base64_file 

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