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