Saving a decoded temporary image to Django Imagefield

前端 未结 3 1828
天命终不由人
天命终不由人 2020-12-28 11:03

I\'m trying to save images which have been passed to me as Base64 encoded text into a Django Imagefield.

But it seems to not be saving correctly. The database repor

相关标签:
3条回答
  • 2020-12-28 11:17

    Another good approach based on this SO answer: https://stackoverflow.com/a/28036805/6143656 tried it and tested in django 1.10

    I made a function for decoded base64 file.

    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)
    

    Then you can call the function

    import decode_base64_file
    
    p = Post(content='My Picture', image=decode_based64_file(your_base64_file))
    p.save()
    
    0 讨论(0)
  • 2020-12-28 11:25

    I guess this is the cleanest and shortest way to do this.

    Here is how you can handle a Base64 encoded image file in a post request at the Django-based (drf also) API end which saves it as an ImageField.

    Let say you have a Model as follows:

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

    So the Corresponding Serializer would be as follows:

     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)
    

    The corresponding View can be as follows:

    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)
    

    Notice In the Serializer I have used Implementation of Base64ImageField provided in the module django-extra-field

    To install this module run the command

    pip install pip install django-extra-fields
    

    Import the same and Done!

    Send (via post method) your image as an Base64 encoded String in JSON object along with any other data you have.

    0 讨论(0)
  • 2020-12-28 11:38

    After reading this answer, I got this to work:

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

    Therefore, I suggest you change your code to:

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

    Then, assuming your ImageField is defined with the upload_to argument set to template_images/template_folders/, you should see the file save down to YOUR_MEDIA_URL/template_images/template_folders/myImage.png

    0 讨论(0)
提交回复
热议问题