[Solved]-Saving Base64ImageField Type using Django Rest saves it as Raw image. How do I convert it to a normal image

2👍

Here is how I solved this problem. None of the answers above had this information

However there are two problems with this approach first of all I do
not know the extension.How do I extract an extension ?

The extension can be extracted by using the following code

from PIL import Image
decodedbytes = base64.decodebytes(str.encode(image_content))
image_stream = io.BytesIO(decodedbytes)
image = Image.open(image_stream)
filetype = image.format #Contains the extension

The next thing is Ill have to check for imageA,B,C,D and E if they
exist and then save each one individually. If I could come up with a
dynamic solution close to something that I have that would work as
well.
The solution to this was simple to use

getattr(job_inst, field).save(content=data , name="img"+filetype)

3👍

The images encoding should come from the client, this is how you can know which format of each one has. Example:

base_64 = "data:image/gif;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzAP/s7P+goOXMv8+fhw/v739......

You will receive it from the client and you know that is a .gif

Once you have validated the extensions and the base64 you can convert it to images and save it in your OS:

Convert string in base64 to image and save on filesystem in Python or Decoding base64 from POST to use in PIL

Once you have the images in your OS, you can link them to your ImageField in the model changing the name property: Set Django's FileField to an existing file

I hope that is clear and helpful!!

0👍

Short answer is :

import imghdr
extension = imghdr.what(file_name, decoded_file)

ref : https://docs.python.org/2/library/imghdr.html OR https://docs.python.org/3/library/imghdr.html

Basically import imghdr is the key in function Base64ImageField.get_file_extension to get / extract the extension of the function.

With below class extend / code you don’t need to do modelJob.instance.imageA.save(content=content,name=”image.jpeg”)

You need to add this class in your codebase to call or for trial purpose you can add in same Serializer class file itself.

from django.core.files.base import ContentFile
import base64
import six
import uuid

class Base64ImageField(serializers.ImageField):
    """
    A Django REST framework field for handling image-uploads through raw post data.
    It uses base64 for encoding and decoding the contents of the file.

    Heavily based on
    https://github.com/tomchristie/django-rest-framework/pull/1268

    Updated for Django REST framework 3.
    """

    def to_internal_value(self, data):                
        # 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:
                self.fail('invalid_image')

            # Generate file name:
            file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
            # Get the file name extension:
            file_extension = self.get_file_extension(file_name, decoded_file)

            complete_file_name = "%s.%s" % (file_name, file_extension, )

            data = ContentFile(decoded_file, name=complete_file_name)

        return super(Base64ImageField, self).to_internal_value(data)

    def get_file_extension(self, file_name, decoded_file):
        import imghdr

        extension = imghdr.what(file_name, decoded_file)
        extension = "jpg" if extension == "jpeg" else extension

        return extension

One more information is you can have

Base64ImageField(
        max_length=None,
        use_url=True,
        required=False,
        allow_null=True,
        allow_empty_file=True
    )

these params in case you want to make this optional.

NOTE :: I had got this code from StackOverflow only, but not remembered from where I got this I had liked this answer too.

Leave a comment