alejoss alejoss - 5 months ago 75
Ajax Question

Django image saved from base64 decoded string is corrupted

I don't know what is wrong here, so I will describe the whole process:

First, I use Croppie to let the user crop an image on the client side. This javascript library is supposed to return a valid

canvas
object encoded in base64. Then I send the image with
$.ajax()
:

croppie_div.croppie('result', {
type: 'canvas',
size: 'original',
format: 'jpeg'
}).then(function(resp){
$.ajax({
url: "{% url 'recortar_carta_ajax' %}",
method: "POST",
data: {'csrfmiddlewaretoken': "{{ csrf_token }}", 'imagen': resp, 'carta_id': "{{ carta_magicpy.id }}"},
success: function(r){
alert(r)
},
error: function(r){
alert(r)
}
});


Then, I get the encoded string in django, decode it and save it to an
ImageField
:

if request.is_ajax():

carta_id = request.POST.get("carta_id")
imagen_b64 = request.POST.get("imagen")

imagen_decodificada = base64.b64decode(imagen_b64)

carta_magicpy = CartaMagicPy.objects.get(id=carta_id)
imagen_django = ContentFile(imagen_decodificada, "imagen.jpeg")
carta_magicpy.imagen.save("imagen.jpeg", imagen_django, save=True)


The saved image is corrupted. When I try to open it with a file browser I get the error:


Error interpreting JPEG image file (Not a JPEG file: starts with 0x75
0xab)


I don't know how to debug this. How can I find the error? Any advice will help.

This is the model:

def ubicar_magicpy(instance, filename):
# Para ubicar las imágenes de magicpy
path = "/".join([instance.grupo.nombre, "imagen.jpeg"])
return path

class CartaMagicPy(models.Model):
imagen = models.ImageField(null=True, upload_to=ubicar_magicpy)

Answer

You should remove the Base64 declarations, as they are not part of the base64 string themselves. You can do it either client side or server side, although the advantage of doing so server side is that if you decide to switch image formats, that string helps you determine which file format is being sent.

This is not the most elegant way of doing it, but you could have:

imagen_decodificada = base64.b64decode(imagen_b64.replace('data:image/jpeg;base64,',''))